首页 > 其他分享 >CF1250A Berstagram 题解

CF1250A Berstagram 题解

时间:2024-04-10 21:58:26浏览次数:18  
标签:include last 数字 题解 位置 Berstagram ch CF1250A now

题面

题意描述的很清楚,这里就不多赘述。

思路

看题,对于每个 \(a_i\),若 \(b_j=a_i\),则将 \(b_j\) 与 \(b_{j-1}\) 的值调换(若 \(j=1\),则序列不变)。一开始想的是最直接的暴力,复杂度为 \(O(nm)\),虽然开了三秒的时限,但 \(4\times10^{10}\) 的数据明显不是三秒钟就能解决的,含恨倒在第 \(28\) 个数据点。

那就换个思路吧。

再回头看一下题目,不妨换个想法来理解题目中的数组 \(a\),将读入的数组 \(a\) 看作读入 \(m\) 次数字 \(a\),将数字 \(a\) 它当前所在的位置与它前一个位置的数进行交换。这样复杂度就降了一个数量级。

以样例 \(1\) 为例

数组 \(b\) 初始:\({1,2,3}\)。

这时读入 \(3\),理解为将数字 \(3\) 所在位置与它前一个位置的数,也就是数字 \(2\) 交换位置。

第一次操作后变为:\({1,3,2}\)。

读入第二个数字 \(2\),理解为将数字 \(2\) 所在位置与它前一个位置的数,也就是数字 \(3\) 交换位置。因为此时数字 \(2\) 的位置在三号位,二号位置是数字 \(3\),故交换它们的位置。

第二次操作后变为:\({1,2,3}\)。

这时读入 \(1\),理解为将数字 \(1\) 所在位置与它前一个位置的数交换位置。但此时数字 \(1\) 在一号位置,由于题目限制,所以不做交换。

第三次操作后变为:\({1,2,3}\)。

剩下两次操作思路一致。

第四次操作后:\({1,3,2}\)。

第五次操作后:\({3,1,2}\)。

代码实现

在代码中,我开了一个结构体,用来储存数字 \(i\),它的最小值和最大值。又开了一个数组 \(tag\),用来记录数字 \(i\) 所在的位置。

初始化

对于每个 \(b_i\),它的初始值是 \(i\),它最靠前的位置和最靠后的位置是它自己。

交换及更新位置

		a = read();
        ll now = tag[a];//数字a现在的位置
        ll last = now - 1;//now的上一个位置
        if(last == 0)
        {
            continue;
        }
        swap(b[now] , b[last]);
        tag[a] = last;
        tag[b[now].num] = now;
        b[last].minn = min(b[last].minn , last);
        b[now].maxn = max(b[now].maxn , now);

结合代码来看,对于每一个交换后的 \(a\),它的位置变为 \(last\),也就是 \(now-1\),明显,此时 \(a\) 的最大值并不会更新,因为交换后 \(a\) 的位置一定比记录的 \(maxn\) 的值小,所以只需要更新最小值。同理,向后移了一个位置的原先的 \(last\) 的位置所对应的数,它的 \(minn\) 值也不会改变,只需要更新 \(maxn\) 的值。

注意,这里交换位置后,原先的 \(now\) 与 \(last\) 所对应的数发生了改变,此时的 \(last\) 这个位置所在值才是 \(a\)。

代码

补充一句话:最后的数组 \(t\) 是为了按顺序输出,与核心思路无关。

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#define ll long long
#define inf 0x3f3f3f3f
#define fr(i , a , b) for(ll i = a ; i <= b ; ++i)
#define fo(i , a , b) for(ll i = a ; i >= b ; --i)
#pragma comment(linker , "/stack : 200000000")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;
inline char gchar()
{
    static char buf[1000000] , *p1 = buf , *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 1000000 , stdin) , p1 == p2) ? EOF : *p1++;
}
inline ll read()
{
    ll x = 0 , f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
	  {
        if(ch == '-')
        {
        	f = -1;
		}
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
	  {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
ll n , m;
ll a;
struct node
{
    ll num , maxn , minn;
}b[1100000] , t[1100000];
ll tag[1100000];//记录数字i所在的位置
signed main()
{
    n = read();
    m = read();
    fr(i , 1 , n)
    {
        b[i].num = b[i].maxn = b[i].minn = tag[i] = i;
    }
    fr(i , 1 , m)
    {
        a = read();
        ll now = tag[a];//数字a现在的位置
        ll last = now - 1;
        if(last == 0)
        {
            continue;
        }
        swap(b[now] , b[last]);
        tag[a] = last;
        tag[b[now].num] = now;
        b[last].minn = min(b[last].minn , last);
        b[now].maxn = max(b[now].maxn , now);
    }
    fr(i , 1 , n)
    {
       t[b[i].num] = (node)b[i];
    }
    fr(i , 1 , n)
    {
        printf("%lld %lld\n" , t[i].minn , t[i].maxn);
    }
    system("pause");
    return 0;
}

标签:include,last,数字,题解,位置,Berstagram,ch,CF1250A,now
From: https://www.cnblogs.com/xhqdmmz/p/18127556

相关文章

  • P8791 [蓝桥杯 2022 国 AC] 内存空间 题解
    题面一道比较简单模拟题,但是要分类讨论一.读完题你应该知道的1.输入一共有T+1行,输入含有空格。(处理1)2.对于每一行变量定义的语句,只会出现一种变量类型,type只可能是int或long,只有一个分号。(处理1,处理2)3.统计内存过程中用B做单位,保证一定有输出,但在输出时要换......
  • CF1681C Double Sort 题解
    一道普及-我写了两个半小时题面。需要注意的是,每次交换需要将a和b两个数组同时交换,因此便可以想到唯一可行情况:a,b序列数字间的大小关系必须一致。举个例子2462131317970612在上面的例子中,两个序列中任意\(i\)和\(j\)满足\(a_i\lea_j\)时\(b_i......
  • CF958F1 Lightsabers (easy) 题解
    题面。不好意思,当我看到\(1\len\le100\),\(1\lem\len\)的那一刻,我承认我心动了。题目没翻译,用翻译软件翻译了才看懂。思路依据题意直接模拟即可。这里我用了三层循环来模拟。第一层为\(len\),表示长度;第二层为\(from\),表示出发点,此时需要遍历的区间的终点\(to=from......
  • CF1040B Shashlik Cooking 题解
    题面。看到这道题的第一眼,就想到用分块思想来解决。思路我们知道,当对任意一个\(i\)进行翻转时,区间\([i-k,i+k]\)内的所有元素都会翻转,每次翻转的总个数为\(2\timesk+1\)。因此,我们可以将所有烤串分成长度为\(len=2\timesk+1\)的\(block=n\divlen\)块,用数组\(L......
  • CF158C Cd and pwd commands 题解
    题面。大模拟,但是有坑点。思路依照题意模拟。用一个字符串\(out\)记录在进行了\(i\)次操作后如果要输出输出的东西,字符串\(in\)和\(s\)来分别记录输入的操作及操作类型。由于输出的第一个字符一定是/,所以可以直接将\(out\)的初始化定为out="/"。这样子可以省去......
  • CF875B Sorting the Coins 题解
    题面。算是比较简单的题目了,自己多手出几个样例就可以发现规律了。强烈建议多读几遍题目!!!!思路设0表示硬币朝上,1表示硬币朝下,则第\(0\)次与第\(n\)操作一定输出\(1\)。因为没有可以操作的对象,前者是由于全部硬币朝上,后者是由于全部硬币朝下,即使没有操作也要遍历一遍。注......
  • CF121A Lucky Sum 题解
    题面。不好意思,又双把通过率拉低了。在CF上交了22次才过。这里给出不同的写法。思路规律其他题解写得都很好,这里不需要再讲述如何推出规律。预处理出前\(5000\)个符合要求的数(其实我也不知道处理多少个刚好够,就随便写了一个数)。接下来借用到一点分块思想,将整个\([l,r]\)......
  • CF1670B Dorms War 题解
    题面。不好意思,把这道题的通过率拉低了,但坑点确实有。思路多出几个数据,我们可以发现,在不报警的前提下,最多可以操作数量是两个特殊字符间的最长距离。解释对于不报警的定义是:每次删除操作进行前,当前的字符串中的所有特殊字符的前一个位置必须不是特殊字符。换句话说,只要当前......
  • CF1817A Almost Increasing Subsequence 题解
    题面。2023.5.18修正关于前缀和数组的说法,与代码适配的思路。题意给定长度为\(n\)一个序列\(a\)以及\(q\)次询问,每次询问给出\(l\)和\(r\),要求找出序列\(a\)在\([l,r]\)内最长的几乎递增子序列。对于几乎递增的定义:如果一个序列中不存在连续的三个数\(x\),\(y\)......
  • CF1737C Ela and Crickets 题解
    题面。原先大佬的题解写的很好,但这里想讲一下不同做法。思路题目中说的\(L\)型有四种情况,很容易就可以想到特殊情况,那就是\(L\)型恰好贴在棋盘的四个角上,这时我们发现,这样子棋子只能在棋盘的其中两条边上移动。对于四个角我们进行四次特判。看普通情况,在手动模拟完样例后......