[考试反思]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)$的。

 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 }
View Code

 

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)$的线段树合并

 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 }
View Code

 

T3:Light

没啥意思的题。。。还是不讲了吧。(关键是我也没机会改出来了

就是大力分类讨论,二分答案与贪心,带权并查集,考虑当前操作是否会影响后续操作。

对着$std$写都写不对。我人都没了。存个代码吧。

  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 }}
View Code

 

posted @ 2020-06-16 14:41  DeepinC  阅读(263)  评论(0编辑  收藏  举报