ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu P5064 [Ynoi2014] 等这场战争结束之后

2022-07-09 22:04:44  阅读:125  来源: 互联网

标签:log luogu 复杂度 查集 Ynoi2014 long P5064 db define


题面传送门
按秩合并并查集写错复杂度假掉以为自己被卡常卡了好久。
首先这种撤销题看上去就是把操作树建立出来然后dfs变成加入与撤销。
然后我们考虑对值域分块,这样看上去求\(k\)小值会可做一些。
首先我们需要确定每个询问在哪个块,这并不困难。我们考虑在dfs时用并查集维护,并查集的根节点维护每个值域块在这个联通块中有多少个。然后询问时逐块确定就可以得知答案在哪个块中。
然后我们考虑确定具体是哪个数。一种simple的想法是枚举每个数,看看是不是在同一个联通块中,但是很遗憾复杂度是有问题的因为可能一种值有很多个。正确的姿势是将同样的值离散到不同的值,这样答案不会变,但是每个值只有一个数,就可以用并查集逐个查询了。
块长取\(\sqrt{\frac{n}{\log n}}\)最优,时空复杂度都是\(O(n\sqrt {n\log n})\),但是实际上开不下这么大的数组,可以看到这道题刻意卡空间了。因此我们将块个数调小,实现上\(B=45\)能卡进空间和时间限制。
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define db double
#define lb long db
#define N (100000+5)
#define M ((N<<2)+5)
#define K (2500+5)
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-9)
#define ull unsigned ll
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((k+1)*(x)+(y))
#define R(n) (1ll*rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;
struct yyy{int to,z;};struct ljb{int head,h[N];yyy f[N];I void add(int x,int y){f[++head]=(yyy){y,h[x]};h[x]=head;}}s;
int n,m,k,x,y,Op[N],X[N],Y[N],A[N],B[N],fa[N],siz[N],st[N],Fr[K],En[K],H,Ans[N];short F[N][46];
I int GF(int x){while(fa[x]^x) x=fa[x];return x;;}I bool cmp(int x,int y){return A[x]<A[y];}
I void Merge(int x,int y){x=GF(x);y=GF(y);if(x==y) return;siz[x]<siz[y]&&(swap(x,y),0);fa[y]=x;for(int i=0;i<=n/k;i++) F[x][i]+=F[y][i];st[++H]=y;siz[x]+=siz[y];}
I void POP(){int x=st[H--];siz[fa[x]]-=siz[x];for(int i=0;i<=n/k;i++) F[fa[x]][i]-=F[x][i];fa[x]=x;}
I void Make(int x){
	int La=H;Op[x]==1&&(Merge(X[x],Y[x]),0);X[x]=GF(X[x]);if(Op[x]==3){for(int i=0;i<=n/k;i++){if(Y[x]>F[X[x]][i]) {Y[x]-=F[X[x]][i];continue;}for(int j=Fr[i];j<=En[i];j++) {Y[x]-=(GF(B[j])==X[x]);if(!Y[x]) {Ans[x]=j;break;}}break;}}
	yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],Make(tmp.to);La^H&&(POP(),0);
}
int main(){
	freopen("1.in","r",stdin);
	int i;scanf("%d%d",&n,&m);k=max(n/45,1);for(i=1;i<=n;i++) scanf("%d",&A[i]),fa[i]=B[i]=i,siz[i]=1;sort(B+1,B+n+1,cmp);for(i=1;i<=n;i++) F[B[i]][i/k]=1;
	for(i=1;i<=m;i++) scanf("%d%d",&Op[i],&X[i]),Op[i]^2?(scanf("%d",&Y[i]),s.add(i-1,i)):(s.add(X[i],i)),Ans[i]=-1;
	for(i=0;i<=n/k;i++) Fr[i]=max(1,i*k),En[i]=min(i*k+k-1,n);Make(0);for(i=1;i<=m;i++) Op[i]==3&&(printf("%d\n",~Ans[i]?A[B[Ans[i]]]:-1));
}

标签:log,luogu,复杂度,查集,Ynoi2014,long,P5064,db,define
来源: https://www.cnblogs.com/275307894a/p/16461948.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有