首页 > 其他分享 >The 2023 ICPC Asia Hefei Regional Contest Test D. Balanced Array

The 2023 ICPC Asia Hefei Regional Contest Test D. Balanced Array

时间:2023-12-03 15:44:06浏览次数:28  
标签:typedef Contest int Regional Hefei long include 2k define

Preface

这题赛场上出了个关键点基本都想到的做法,但因为一个地方卡住了没过去导致不得不选择弃掉这道题

赛后补了下发现\(O(n\log n)\)的做法是只差临门一脚了,但\(O(n)\)的做法还是trick性挺强的


Solution

首先考虑枚举\(k\),不难发现此时合法的前缀一定是个连续的区间,其中区间的左端点为\(2k+1\)

那么可以先暴力验证\(a_1+a_{2k+1}\)与\(2a_{k+1}\)的大小关系,若符合则考虑往后推移的过程

我们很容易想到差分,设\(d_i=a_{i+1}-a_i\),那么对于当前的符合条件的三元组\((1,k+1,2k+1)\),能往后推一步的充要条件就是\(d_1+d_{2k+1}=2d_{k+1}\)

同理,如果要推\(t\)步则需要满足\(d_{1+j}+d_{2k+1+j}=2d_{k+1+j}(0\le j<t)\)

考虑利用Hash来把多位放在一起比较,利用其每一位的线性不变性,我们可以直接先Hash在加起来判断

假设要验证间隔为\(k\),合法的前缀区间是否为\([2k+1,L]\),则等价于判断:

\[\operatorname{hash}(1,L-2k-1)+\operatorname{hash}(2k+1,L-1)=2\operatorname{hash}(k+1,L-k-1) \]

直接用二分找到最远的合法的分界点即可,最后统计答案就随便处理以下即可

总复杂度\(O(n\log n)\)

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef __int128 i128;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=2e6+5;
class FileInputOutput
{
    private:
        static const int S=1<<21;
        #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
        char Fin[S],*A,*B;
    public:
        inline void read_int(int& x)
        {
            x=0; char ch; while (!isdigit(ch=tc()));
            while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
        }
        inline int trs(const char& ch)
        {
        	if ('0'<=ch&&ch<='9') return ch-'0';
        	if ('a'<=ch&&ch<='z') return ch-'a'+10;
        	if ('A'<=ch&&ch<='Z') return ch-'A'+36;
        }
        inline void read_b62(int& x)
        {
        	x=0; char ch; while (isspace(ch=tc()));
			while (x=x*62+trs(ch),!isspace(ch=tc()));	
        }
        #undef tc
}F;
const int mod1=998244353,mod2=1e9+7;
struct Hasher
{
	int x,y;
	inline Hasher(CI X=0,CI Y=0)
	{
		x=(X%mod1+mod1)%mod1; y=(Y%mod2+mod2)%mod2;
	}
	friend inline bool operator == (const Hasher& A,const Hasher& B)
	{
		return A.x==B.x&&A.y==B.y;
	}
	friend inline Hasher operator + (const Hasher& A,const Hasher& B)
	{
		return Hasher((A.x+B.x)%mod1,(A.y+B.y)%mod2);
	}
	friend inline Hasher operator - (const Hasher& A,const Hasher& B)
	{
		return Hasher((A.x-B.x+mod1)%mod1,(A.y-B.y+mod2)%mod2);
	}
	friend inline Hasher operator * (const Hasher& A,const Hasher& B)
	{
		return Hasher(1LL*A.x*B.x%mod1,1LL*A.y*B.y%mod2);
	}
}h[N],pw[N]; int n,a[N],d[N],f[N];
const Hasher seed=Hasher(31,131);
inline Hasher get_hsh(CI l,CI r)
{
	return h[r]-h[l-1]*pw[r-l+1];
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i; for (F.read_int(n),i=1;i<=n;++i) F.read_b62(a[i]);
	for (i=1;i<=n;++i) d[i]=a[i+1]-a[i];
	for (pw[0]=Hasher(1,1),i=1;i<=n;++i) pw[i]=pw[i-1]*seed;
	for (i=1;i<=n;++i) h[i]=h[i-1]*seed+Hasher(d[i],d[i]);
	for (i=1;2*i+1<=n;++i) if (a[1]+a[2*i+1]==2*a[i+1])
	{
		int l=2*i+1,r=n,mid,ret; while (l<=r)
		if (mid=l+r>>1,get_hsh(1,mid-2*i-1)+get_hsh(2*i+1,mid-1)==Hasher(2,2)*get_hsh(i+1,mid-i-1)) ret=mid,l=mid+1; else r=mid-1;
		++f[2*i+1]; --f[ret+1];
	}
	for (i=1;i<=n;++i) f[i]+=f[i-1];
	for (i=1;i<=n;++i) putchar(f[i]?'1':'0');
	return 0;
}

但这题\(2\times 10^6\)跑1s显然就是想卡掉带\(\log\)做法,因此我们思考如何去掉这个\(\log\)

很容易发现当一段前缀\([2k+1,pos]\)合法后,其实我们就没有必要再去检验前缀小于等于\(pos\)的所有区间了

因此可以用一个指针来维护当前最靠右的合法的前缀,每次判断能否向后移动即可

总复杂度\(O(n)\)

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef __int128 i128;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=2e6+5;
class FileInputOutput
{
    private:
        static const int S=1<<21;
        #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
        char Fin[S],*A,*B;
    public:
        inline void read_int(int& x)
        {
            x=0; char ch; while (!isdigit(ch=tc()));
            while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
        }
        inline int trs(const char& ch)
        {
        	if ('0'<=ch&&ch<='9') return ch-'0';
        	if ('a'<=ch&&ch<='z') return ch-'a'+10;
        	if ('A'<=ch&&ch<='Z') return ch-'A'+36;
        }
        inline void read_b62(int& x)
        {
        	x=0; char ch; while (isspace(ch=tc()));
			while (x=x*62+trs(ch),!isspace(ch=tc()));	
        }
        #undef tc
}F;
const int mod1=998244353,mod2=1e9+7;
struct Hasher
{
	int x,y;
	inline Hasher(CI X=0,CI Y=0)
	{
		x=(X%mod1+mod1)%mod1; y=(Y%mod2+mod2)%mod2;
	}
	friend inline bool operator == (const Hasher& A,const Hasher& B)
	{
		return A.x==B.x&&A.y==B.y;
	}
	friend inline Hasher operator + (const Hasher& A,const Hasher& B)
	{
		return Hasher((A.x+B.x)%mod1,(A.y+B.y)%mod2);
	}
	friend inline Hasher operator - (const Hasher& A,const Hasher& B)
	{
		return Hasher((A.x-B.x+mod1)%mod1,(A.y-B.y+mod2)%mod2);
	}
	friend inline Hasher operator * (const Hasher& A,const Hasher& B)
	{
		return Hasher(1LL*A.x*B.x%mod1,1LL*A.y*B.y%mod2);
	}
}h[N],pw[N]; int n,a[N],d[N],f[N];
const Hasher seed=Hasher(31,131);
inline Hasher get_hsh(CI l,CI r)
{
	return h[r]-h[l-1]*pw[r-l+1];
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i,j; for (F.read_int(n),i=1;i<=n;++i) F.read_b62(a[i]);
	for (i=1;i<=n;++i) d[i]=a[i+1]-a[i];
	for (pw[0]=Hasher(1,1),i=1;i<=n;++i) pw[i]=pw[i-1]*seed;
	for (i=1;i<=n;++i) h[i]=h[i-1]*seed+Hasher(d[i],d[i]);
	for (j=0,i=1;2*i+1<=n;++i) if (a[1]+a[2*i+1]==2*a[i+1])
	{
		if (j<2*i+1) f[j=2*i+1]=1;
		auto check=[&](CI pos)
		{
			return get_hsh(1,pos-2*i-1)+get_hsh(2*i+1,pos-1)==Hasher(2,2)*get_hsh(i+1,pos-i-1);
		};
		while (j<n&&check(j+1)) f[++j]=1;
	}
	for (i=1;i<=n;++i) putchar(f[i]?'1':'0');
	return 0;
}

标签:typedef,Contest,int,Regional,Hefei,long,include,2k,define
From: https://www.cnblogs.com/cjjsb/p/17873278.html

相关文章

  • The 2023 ICPC Asia Hefei Regional Contest Test I. Linguistics Puzzle
    Preface这题yysy真不难,但比赛的时候想出做法后没时间写了,只能遗憾地看着倒计时结束Solution直接上爆搜复杂度肯定会爆,考虑有哪些数是可以不用搜直接推出来的首先样例启发我们\(0,1\)这两个数很好确定,因为\(0\)对应的字母单独出现的次数肯定最多,而\(1\)作为两位的开头出现的次......
  • ALGO ARTIS Programming Contest 2023 Autumn(AtCoder Regular Contest 168)
    Preface先补一下这场ARC的博客,因为在来回合肥的路上一直在想这场的CD,所以有空后就先把这场补了A-<Inversion>不难发现对于一段连续的<,设其长度为\(x\),则它最少要贡献\(\frac{x(x+1)}{2}\)的答案而我们很容易构造一种方案刚好满足这个下界,只要让每段的结束比下一段的开头大......
  • The 2021 Sichuan Provincial Collegiate Programming Contest
    Preface下下周还要去打重庆市赛,最近就找些省赛来练练手不得不说省赛的签到题是真的多,人均10+的过题看起来还是很恐怖的这场虽然因为徐神缺席,而且前面的题目都让祁神来写导致罚时略高,但无所谓反正最后也摸到了11题(主要是没有字符串)A.Chuanpai某不知题意的签到#include<bits......
  • The 2023 ICPC Asia Hefei Regional Contest
    目录写在前面赛时FEJGC补题写在最后写在前面赛时题目按照过题顺序排序,赛后补题按照个人向难度排序。省流版:要寄了吗?没寄。赛时F开局我正开,过了五分钟发现已经有人手刹了F了,几分钟之内大屏幕上一车提交,看了一下发现是超级签到于是Nebulyu上机开写。冲完之后发现T了????\(10......
  • AtCoder Beginner Contest 330
    B-MinimizeAbs1思维题题意:给定一个范围,你选择一个数,使得思路:如果A[i]在l,r中间,那么直接打印就行,如果不是就打印就近的usingnamespacestd;voidsolve(){ intn,l,r; cin>>n>>l>>r; for(inti=1;i<=n;i++){ intx; cin>>x; if(x<l){ cout<<l<<"......
  • AtCoder Beginner Contest 326
    A-2UP3DOWN#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongvoidsolve(){inta,b;cin>>a>>b;if(a<bandb-a<=2)cout<<"Yes\n";elseif(a>banda......
  • AtCoder Beginner Contest 322
    A-FirstABC2#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#definempmake_pairusingvi=vector<int>;usingpii=pair<int,int>;voidsolve(){intn;strings;cin>>n>>s;......
  • TOYOTA SYSTEMS Programming Contest 2023(AtCoder Beginner Contest 330)
    TOYOTASYSTEMSProgrammingContest2023(AtCoderBeginnerContest330)A-CountingPassesintmain(){IOS;cin>>n>>m;intans=0;rep(i,1,n)cin>>k,ans+=k>=m;cout<<ans;return0;}B-......
  • AtCoder Beginner Contest 330
    A-CountingPasses(abc330A)题目大意给定\(n\)个学生的分数,以及及格分\(x\),问多少人及格了。解题思路依次判断即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){ios::sync_with_stdio(false);cin.ti......
  • The 2021 ICPC Asia Shenyang Regional Contest
    Preface合肥前的最后一场VP了,本来计划是我和祁神两个人打,但后面徐神还是来救场了然后这场我们过的最难的两题都是徐神切的,直接给我们抬进Au区了属于是而且徐神最后也差一点写出G(TLEon72),同时也一眼秒了D(没时间写了),看来这场让三个徐神来打感觉10题随便出线了A.ABiteofTey......