[考试反思]0608四校联考第二轮day2:消耗
还是退役的分。
题不太好。非常卡常。几乎没部分分。$T3$毫无意义。
$T1$是若干个讲过的原题组合而成的,然而好像很麻烦不是很想写,就先看$T2$了。
$T2$感觉像原题然而并不是。然后一直在尝试想。
没花多少时间想出了$O(n^2)$的暴力。然后花了挺长时间搞出了$O(nlog^2n)$的做法。
对拍都挂上了。本来抱着$80$打底卡常也许能$AC$的念想。然后被毒瘤卡常了只剩下$n^2$的分。
$T3$惯例神仙题,并没有时间去写$10pts$的暴力(又难写又分少)
这一轮两天加起来的成绩在总榜上不算特别低,但还是联赛比我低的把我翻了联赛比我高的我翻不动,所以又退役了。
也只能尽力去考吧,剩下的交给出题人和出数据的和评测机。
T1:endless
大意:对于所有平方串$[i,i+2l-1]$,对于所有$j\in [i,i+l-1]$将$(j,j+l)$连上权值为$w_l$的边。求最小生成森林。$n \le 3 \times 10^5$
生成树算法就那么几个,平时常用的也就是更少了,这题$Boruvka$显然不可行,于是考虑$Kruscal$
所以还是从小到大枚举边权,然后看能连上多少边。
那么对于特定长度处理有哪些点对之间能连边这已经是个老问题了,设立哨兵节点求相邻哨兵的$lcp,lcs$然后区间连边即可。
区间连边这种东西这里写的是倍增并查集。查询$[a,a+2^i),[b,b+2^i]$两个区间是否已经完全对位合并。
如果合并过了就直接返回没什么问题,否则就递归下去合并直到叶节点就做普通并查集合并,并且上传信息。
会递归下去一定代表在这一轮里你会合并两个元素,所以总复杂度是$O(n\ ln \ n+n\ log\ n)$的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ull unsigned long long 4 const int S=333333; 5 long long ans;int n,w[S],f[19][S],SA[2][S],rk[2][S],h[2][S],a[S],ST[2][19][S],lb[S],r[S]; 6 int find(int d,int x){return f[d][x]==x?x:f[d][x]=find(d,f[d][x]);} 7 void get_SA(int*a,int*sa,int*rk,int*h,int o,int m=n){ 8 static int b[S],x[S],y[S]; 9 for(int i=1;i<=n;++i)b[i]=0,x[i]=a[i]; 10 for(int i=1;i<=n;++i)b[x[i]]++; 11 for(int i=1;i<=n;++i)b[i]+=b[i-1]; 12 for(int i=1;i<=n;++i)sa[b[x[i]]--]=i; 13 for(int len=1;len<=n;len<<=1){ 14 int num=0; 15 for(int i=n-len+1;i<=n;++i)y[++num]=i; 16 for(int i=1;i<=n;++i)if(sa[i]>len)y[++num]=sa[i]-len; 17 for(int i=1;i<=m;++i)b[i]=0; 18 for(int i=1;i<=n;++i)b[x[i]]++; 19 for(int i=1;i<=m;++i)b[i]+=b[i-1]; 20 for(int i=n;i;--i)sa[b[x[y[i]]]--]=y[i]; 21 for(int i=1;i<=n;++i)y[i]=x[i],x[i]=0; 22 x[sa[1]]=m=1; 23 for(int i=2;i<=n;++i)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+len]==y[sa[i-1]+len]?m:++m; 24 if(m==n)break; 25 } 26 for(int i=1;i<=n;++i)rk[sa[i]]=i,y[i]=0; 27 for(int i=1,k=0;i<=n;h[rk[i++]]=k,k-=k>0)while(a[i+k]==a[sa[rk[i]-1]+k])k++; 28 for(int i=1;i<=n;++i)ST[o][0][i]=h[i]; 29 for(int i=1;i<19;++i)for(int j=1;j+(1<<i)-1<=n;++j)ST[o][i][j]=min(ST[o][i-1][j],ST[o][i-1][j+(1<<i-1)]); 30 } 31 int Min(int o,int l,int r){int b=lb[r-l+1];return min(ST[o][b][l],ST[o][b][r-(1<<b)+1]);} 32 int lcs(int a,int b){if(rk[0][a]>rk[0][b])swap(a,b);return Min(0,rk[0][a]+1,rk[0][b]);} 33 int lcp(int a,int b){a=n+1-a;b=n+1-b;if(rk[1][a]>rk[1][b])swap(a,b);return Min(1,rk[1][a]+1,rk[1][b]);} 34 bool merge(int B,int x,int y,int w){ 35 if(find(B,x)==find(B,y))return 0; 36 if(B==0){f[0][find(0,x)]=find(0,y),ans+=w;return 1;} 37 if(!(merge(B-1,x,y,w)|merge(B-1,x+(1<<B-1),y+(1<<B-1),w)))return f[B][find(B,x)]=find(B,y),0; 38 return 1; 39 } 40 int main(){ 41 freopen("endless.in","r",stdin);freopen("endless.out","w",stdout); 42 for(int i=0;i<19;++i)for(int j=1<<i;j<2<<i&&j<S;++j)lb[j]=i; 43 int t;cin>>t;while(t--){ 44 scanf("%d",&n);ans=0; 45 for(int i=0;i<19;++i)for(int j=1;j+(1<<i)-1<=n;++j)f[i][j]=j; 46 for(int i=1;i<=n;++i)scanf("%d",&a[i]); 47 get_SA(a,SA[0],rk[0],h[0],0); 48 reverse(a+1,a+1+n); 49 get_SA(a,SA[1],rk[1],h[1],1); 50 for(int i=1;i+i<=n;++i)scanf("%d",&w[i]),r[i]=i; 51 sort(r+1,r+1+(n>>1),[](int a,int b){return w[a]<w[b];}); 52 for(int _=1,l;l=r[_],_+_<=n;++_){ 53 for(int i=l;i+l<=n;i+=l){ 54 int s=min(l,lcs(i,i+l)),p=min(l,lcp(i,i+l)),x=s+p-1,B; 55 if(x<l)continue; 56 B=lb[x]; merge(B,i-p+1,i-p+1+l,w[l]); merge(B,i+s-(1<<B),i+l+s-(1<<B),w[l]); 57 } 58 } 59 printf("%lld\n",ans); for(int i=1;i<=n;++i)a[i]=0; 60 } 61 }
T2:图
大意:给定$n$点无向图,不断进行:如果$a<b<c$且$ab$有边$ac$有边那么你会把$bc$也连上。求最终的图中用$n$种颜色染色,边两端点不同色方案数。$n,m \le 10^6$
一个小的结论是:对于点$i$,它所连出的所有边中比它大的点会构成完全图。
也就是说$i$能到的点$x,y$,那么$x,y$也一定可以互相到达。
我们用$set$维护每个点的出边,那么就会有一些继承关系。
当前点$x$的出边会交给它能到达的所有点,但是仔细一想,只要交给$y=upperbound(x)$就可以了,因为这样$y$就能到达其它它能到达的点。
然后$y$也就会继续交给其它点一直传递下去。这是没有问题的。
所以就是启发式一发,每次到一个点的时候把自己删掉就好了。时间复杂度$O(nlog^2n)$。
实际运行效率高于$O(nlogn)$的线段树合并
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int ans=1,n,m; set<int>s[1000005]; 4 int main(){ 5 freopen("graph.in","r",stdin);freopen("graph.out","w",stdout); 6 scanf("%d%d",&n,&m); 7 for(int i=1,a,b;i<=m;++i)scanf("%d%d",&a,&b),s[a].insert(b); 8 for(int i=1,y;i<=n;++i){ 9 s[i].erase(i); y=*s[i].begin(); 10 ans=1ll*ans*(n-s[i].size())%998244353; 11 if(s[i].size()>s[y].size())swap(s[i],s[y]); 12 for(auto x:s[i])s[y].insert(x); 13 }printf("%d",ans); 14 }
T3:Light
没啥意思的题。。。还是不讲了吧。(关键是我也没机会改出来了
就是大力分类讨论,二分答案与贪心,带权并查集,考虑当前操作是否会影响后续操作。
对着$std$写都写不对。我人都没了。存个代码吧。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define S 222 4 #define pb push_back 5 #define nxt(i,l) i==l-1?0:i+1 6 #define cir(s,t,l) for(int i=s%l;i!=t;i=nxt(i,l)) 7 int t,n,a[S],b[S],has[S][S],share[S][S],bl[S],f[S],st[S]; vector<int>E[S],R; 8 void reset(int n){for(int i=1;i<=n;++i)st[i]=0,f[i]=i;} 9 int find(int x){return x==f[x]?x:f[x]=find(f[x]);} 10 void merge(int x,int y){if(find(x)!=find(y))st[f[f[x]]=f[y]]|=st[f[x]];} 11 int pos(vector<int>&v,int x){for(int i=0;i<v.size();++i)if(v[i]==x)return i;return -1;} 12 void cut(int e,int x){cerr<<e<<' '<<x<<endl; 13 R=E[x]; int A=a[e],B=b[e],oA=pos(R,A),oB=pos(R,B),L=R.size(); 14 for(int i=1;i<=e+4;++i)has[x][i]=0; E[x].clear(); 15 cir(oA,(oB+1)%L,L)E[x].pb(R[i]),has[x][R[i]]=1; 16 cir(oB,(oA+1)%L,L)E[e+1].pb(R[i]),has[e+1][R[i]]=1; 17 E[x].pb(e+4); E[e+1].pb(e+4); has[x][e+4]=has[e+1][e+4]=1; share[x][e+1]=e+4; 18 for(int i=1;i<=e;++i)share[i][e+1]=share[e+1][i]=share[x][i]; 19 } 20 bool chk(int n){ 21 memset(has,0,sizeof has);memset(share,0,sizeof share);for(int i=1;i<=n+1;++i)E[i].clear(); 22 for(int i=1;i<5;++i)E[1].pb(i),has[1][i]=1; 23 for(int i=1,x,y,A,B;A=a[i],B=b[i],x=y=0,i<=n;++i){ 24 for(int j=1;j<=i;++j)if(has[j][A]|has[j][B])(x?y:x)=j; 25 if(!x)return 0; if(!y){cut(i,x);continue;} 26 for(int j=1;j<=i+4;++j)bl[j]=0; 27 for(auto z:E[x])bl[z]|=1; 28 for(auto z:E[y])bl[z]|=2; 29 bl[A]=bl[B]=0; reset(n+4); 30 for(int j=i+1;j<=n;++j)if(a[j]>=i+4)merge(a[j],j+4);else if(bl[a[j]])st[j+4]|=1<<bl[a[j]]-1; 31 for(int j=i+1;j<=n;++j)if(b[j]>=i+4)merge(b[j],j+4);else if(bl[b[j]])st[j+4]|=1<<bl[b[j]]-1; 32 int ST=st[find(i+4)]; 33 if((ST&3)==3)return 0; 34 if(ST^4){cut(i,!ST||ST&1?x:y);continue;} 35 if(B!=share[x][y])swap(A,B);cerr<<n<<' '<<i<<' '<<"ohhh"<<endl; 36 int C=1;while(bl[C]^3)C++;bl[C]=0; 37 int Ax=pos(E[x],A),Bx=pos(E[x],B),Cx=(E[x],C),Ay=pos(E[y],A),By=pos(E[y],B),Cy=pos(E[y],C),sx=E[x].size(),sy=E[y].size(),t; 38 if(nxt(Bx,sx)!=Cx&&nxt(Cx,sx)!=Bx) 39 if(nxt(Ax,sx)==Bx)cir(Bx+1,Cx,sx)bl[E[x][i]]=0; 40 else cir(Cx+1,Bx,sx)bl[E[x][i]]=0; 41 if(nxt(By,sy)!=Cy&&nxt(Cy,sy)!=By) 42 if(nxt(Ay,sy)==By)cir(By+1,Cy,sy)bl[E[y][i]]=0; 43 else cir(Cy+1,By,sy)bl[E[y][i]]=0; 44 reset(n+4); 45 for(int j=i+1;j<=n;++j)if(a[j]>=i+4||a[j]!=B)merge(a[j],i+4);else if(bl[a[j]])st[j+4]|=1<<bl[a[j]]-1; 46 for(int j=i+1;j<=n;++j)if(b[j]>=i+4||b[j]!=B)merge(b[j],i+4);else if(bl[b[j]])st[j+4]|=1<<bl[b[j]]-1; 47 ST=st[find(B)]; 48 if(ST==1)cut(i,x); 49 if(ST==2)cut(i,y); 50 if(ST==3)return 0; 51 if(!ST)cut(i,nxt(Bx,sx)!=Cx&&nxt(Cx,sx)!=Bx?y:x); 52 }return 1; 53 } 54 int main(){freopen("light.in","r",stdin);cin>>t;while(t--){ 55 cin>>n; for(int i=1;i<=n;++i)cin>>a[i]>>b[i]; 56 int l=0,r=n,m,a; 57 while(m=l+r>>1,l<=r)if(chk(m))a=l=m,l++;else r=m-1; 58 cout<<a<<endl; 59 }} 60 #include<bits/stdc++.h> 61 using namespace std; 62 struct dsu{ 63 vector<int>mask,p; int n; 64 dsu(int n):n(n){ 65 mask.resize(n);p.resize(n); 66 for(int i=0;i<n;++i)mask[i]=0,p[i]=i; 67 } 68 inline int find(int x){ 69 while(x!=p[x])x=p[x]=p[p[x]]; 70 return x; 71 } 72 inline bool unite(int x,int y){ 73 x=find(x); y=find(y); 74 if(x==y)return 0; 75 else return p[x]=y,mask[y]|=mask[x],1; 76 } 77 }; 78 int main(){freopen("light.in","r",stdin); int tt; cin>>tt; while(tt--){ 79 int n; cin>>n; 80 vector<int>a(n),b(n); 81 for(int i=0;i<n;++i)cin>>a[i]>>b[i],--a[i],--b[i]; 82 auto check=[&](int n){ 83 vector<vector<int>>seq(n+1); 84 vector<vector<bool>>has(n+1,vector<bool>(n+4,0)); 85 vector<vector<int>>share(n+1,vector<int>(n+1,-1)); 86 for(int i=0;i<4;++i)seq[0].push_back(i),has[0][i]=1; 87 auto put=[&](int i,int x){cerr<<i+1<<' '<<x+1<<endl; 88 vector<int>polygon=seq[x]; 89 int id_a=-1,id_b=-1; 90 for(int j=0;j<(int)polygon.size();++j){ 91 if(a[i]==polygon[j])id_a=j; 92 if(b[i]==polygon[j])id_b=j; 93 } 94 for(int j=0;j<i+4;++j)has[x][j]=0; 95 seq[x].clear(); 96 for(int j=id_a;;j=(j+1)%polygon.size()){ 97 seq[x].push_back(polygon[j]); 98 has[x][polygon[j]]=1; 99 if(j==id_b)break; 100 } 101 seq[x].push_back(i+4); 102 has[x][i+4]=1; 103 for(int j=id_b;;j=(j+1)% polygon.size()){ 104 seq[i+1].push_back(polygon[j]); 105 has[i+1][polygon[j]]=1; 106 if(j==id_a)break; 107 } 108 seq[i+1].push_back(i+4); 109 has[i+1][i+4]=1; 110 for(int j=0;j<=i;++j)share[i+1][j]=share[j][i+1]=share[x][j]; 111 share[x][i+1]=share[i+1][x]=i+4; 112 }; 113 for(int i=0,x,y;x=y=-1,i<n;++i){ 114 for(int j=0;j<=i;++j)if(has[j][a[i]]&&has[j][b[i]])(x==-1?x:y)=j; 115 if(x==-1)return 0; 116 if(y==-1){put(i,x);continue;} 117 vector<int>belong(i+4); 118 for(auto j:seq[x])belong[j]|=1; 119 for(auto j:seq[y])belong[j]|=2; 120 belong[a[i]]=belong[b[i]]=0; 121 dsu p(n+4); 122 for(int j=i;j<n;++j){ 123 if(a[j]<i+4){if(belong[a[j]])p.mask[j+4]|=1<<(belong[a[j]]-1);} 124 else p.unite(a[j],j+4); 125 if(b[j]<i+4){if(belong[b[j]])p.mask[j+4]|=1<<(belong[b[j]]-1);} 126 else p.unite(b[j],j+4); 127 } 128 int mask=p.mask[p.find(i+4)]; 129 if((mask&3)==3)return 0; 130 if(mask&1)put(i,x); 131 else if(mask&2)put(i,y); 132 else if(!mask)put(i,x); 133 else{cerr<<n<<' '<<i+1<<' '<<"ohhh"<<endl; 134 if(b[i]!=share[x][y])swap(a[i],b[i]); 135 int c=0; 136 while(belong[c]!=3)++c; 137 belong[c]=0; 138 int id_a_x=-1,id_b_x=-1,id_c_x=-1; 139 for(int j=0;j<(int)seq[x].size();++j) 140 if(seq[x][j]==a[i])id_a_x=j; 141 else if(seq[x][j]==b[i])id_b_x=j; 142 else if(seq[x][j]==c)id_c_x=j; 143 int id_a_y=-1,id_b_y=-1,id_c_y=-1; 144 for(int j=0;j<(int)seq[y].size();++j) 145 if(seq[y][j]==a[i])id_a_y=j; 146 else if(seq[y][j]==b[i])id_b_y=j; 147 else if(seq[y][j]==c)id_c_y=j; 148 bool simple_x=id_c_x==(id_b_x+1)%(int)seq[x].size()||(id_c_x+1)%(int)seq[x].size()==id_b_x; 149 bool simple_y=id_c_y==(id_b_y+1)%(int)seq[y].size()||(id_c_y+1)%(int)seq[y].size()==id_b_y; 150 if(!simple_x) 151 if((id_a_x+1)%(int)seq[x].size()==id_b_x) 152 for(int j=(id_b_x+1)% seq[x].size();j!=id_c_x;j=(j+1)% seq[x].size())belong[seq[x][j]]=0; 153 else for(int j=(id_c_x+1)% seq[x].size();j!=id_b_x;j=(j+1)% seq[x].size())belong[seq[x][j]]=0; 154 if(!simple_y) 155 if((id_a_y+1)%(int)seq[y].size()==id_b_y) 156 for(int j=(id_b_y+1)% seq[y].size();j!=id_c_y;j=(j+1)% seq[y].size())belong[seq[y][j]]=0; 157 else for(int j=(id_c_y+1)% seq[y].size();j!=id_b_y;j=(j+1)% seq[y].size())belong[seq[y][j]]=0; 158 dsu p(n+4); 159 for(int j=i;j<n;++j){ 160 if(a[j]<i+4&&a[j]!=b[i]){if(belong[a[j]])p.mask[j+4]|=1<<(belong[a[j]]-1);} 161 else p.unite(a[j],j+4); 162 if(b[j]<i+4&&b[j]!=b[i]){if(belong[b[j]])p.mask[j+4]|=1<<(belong[b[j]]-1);} 163 else p.unite(b[j],j+4); 164 } 165 int mask=p.mask[p.find(b[i])]; 166 if(mask==3)return 0; 167 else if(mask==1)put(i,y); 168 else if(mask==2)put(i,x); 169 else if(simple_x)put(i,x); 170 else put(i,y); 171 } 172 }return 1; 173 }; 174 int l=0,r=n; 175 while(l<r){ 176 int mid=(l+r+1)>>1; 177 if(check(mid))l=mid; else r=mid-1; 178 } 179 cout<<l<<"\n"; 180 }}