[luogu3733]八纵八横

Posted pywbktda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu3733]八纵八横相关的知识,希望对你有一定的参考价值。

根据$[WC2011]XOR$的思路,每次暴力重构线性基,令$l‘=frac{l^{2}}{w}$,则有一个$nql‘$的做法(这里线性基位数很多,所以要用bitset)
由于初始连通,因此每一个环一定可以由若干个[树边+1条非树边]的环构成(构成指异或),那么预处理出每一个操作的环大小,相当于维护一个支持插入和删除的线性基(修改操作可以看成删除+插入操作)
证明:归纳k条新边($k=1$显然成立)可以划分,对$k+1$条新边的环,设新边依次为$(l1,r1),(l2,r2),……,(l_{k+1},r_{k+1})$,前k条边所构成的环被划分,多出的部分为树边上的$(l_{1},r_{k}),(l_{1},r_{k+1}),({r_{k},l_{k+1})}$和新边$(l_{k+1},r_{k+1})$,容易发现这个恰好构成了[树边+$(l_{k+1},r_{k+1})$]的环
但线性基无法支持删除,因此用线段树分治:将操作打在区间上,在当前点到根的链上的每一个点维护一个线性基,时间复杂度$o((nlog_{2}n+l‘)qlog_{2}q)$(要注意$q=0$的情况,特判$l>r$)
技术图片
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 1005
  4 #define bt bitset<N>
  5 #define L (k<<1)
  6 #define R (L+1)
  7 #define mid (l+r>>1) 
  8 struct ji{
  9     int nex,to;
 10     bt len;
 11 }edge[N];
 12 int V,E,n,m,t,q,x,y,head[N],vis[N],tim[N];
 13 char s[N];
 14 bt o,sh[N],f[31][N];
 15 pair<bt,bt>val[N];
 16 vector<bt>v[N<<2];
 17 void read(){
 18     scanf("%s",s);
 19     o.reset();
 20     int l=strlen(s);
 21     for(int i=0;i<l;i++)o[l-i-1]=s[i]-0;
 22 }
 23 void write(bt o){
 24     bool flag=0;
 25     for(int i=N-6;i>=0;i--)
 26         if ((flag)||(o[i])){
 27             x=o[i];
 28             printf("%d",x);
 29             flag=1;
 30         }
 31     if (!flag)printf("0");
 32     printf("
");
 33 }
 34 void add(bt x){
 35     for(int i=N-6;i>=0;i--)
 36         if (x[i])
 37             if (f[V][i].any())x^=f[V][i];
 38             else{
 39                 f[V][i]=x;
 40                 break;
 41             }
 42 }
 43 bt query(){
 44     o.reset();
 45     for(int i=N-6;i>=0;i--)
 46         if (!o[i])o^=f[V][i];
 47     return o;
 48 }
 49 void add(int x,int y,bt z){
 50     edge[E].nex=head[x];
 51     edge[E].to=y;
 52     edge[E].len=z;
 53     head[x]=E++;
 54 }
 55 void dfs(int k,bt x){
 56     vis[k]=1;
 57     sh[k]=x;
 58     for(int i=head[k];i!=-1;i=edge[i].nex)
 59         if (!vis[edge[i].to])dfs(edge[i].to,x^edge[i].len);
 60         else add(sh[edge[i].to]^sh[k]^edge[i].len);
 61 }
 62 void New(){
 63     V++;
 64     for(int i=0;i<N-5;i++)f[V][i]=f[V-1][i];
 65 }
 66 void update(int k,int l,int r,int x,int y,bt z){
 67     if ((l>y)||(x>r))return;
 68     if ((x<=l)&&(r<=y)){
 69         v[k].push_back(z);
 70         return;
 71     }
 72     update(L,l,mid,x,y,z);
 73     update(R,mid+1,r,x,y,z);
 74 }
 75 void dfs(int k,int l,int r){
 76     if (l>r)return;
 77     New();
 78     for(int i=0;i<v[k].size();i++)add(v[k][i]);
 79     if (l==r)write(query());
 80     else{
 81         dfs(L,l,mid);
 82         dfs(R,mid+1,r);
 83     }
 84     V--;
 85 }
 86 int main(){
 87     scanf("%d%d%d",&n,&m,&q);
 88     memset(head,-1,sizeof(head)); 
 89     for(int i=1;i<=m;i++){
 90         scanf("%d%d",&x,&y);
 91         read();
 92         add(x,y,o);
 93         add(y,x,o); 
 94     }
 95     o.reset();
 96     dfs(1,o);
 97     for(int i=1;i<=q;i++){
 98         scanf("%s",s);
 99         if (s[0]==A){
100             scanf("%d%d",&x,&y);
101             read();
102             tim[++t]=i;
103             val[t]=make_pair(sh[x]^sh[y],o);
104         }
105         else{
106             scanf("%d",&x);
107             update(1,1,q,tim[x],i-1,val[x].first^val[x].second);
108             if (s[1]==a)tim[x]=-1;
109             else{
110                 read();
111                 tim[x]=i;
112                 val[x].second=o;
113             }
114         }
115     }
116     for(int i=1;i<=t;i++)
117         if (tim[i]>0)update(1,1,q,tim[i],q,val[i].first^val[i].second);
118     write(query());
119     dfs(1,1,q);
120 }
View Code

 

以上是关于[luogu3733]八纵八横的主要内容,如果未能解决你的问题,请参考以下文章

线段树分治 线性基luoguP3733 [HAOI2017]八纵八横

loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)

[HAOI2017]八纵八横 线性基

HAOI2017 八纵八横——线段树分治+线性基

线段树分治总结

PA2013BZOJ3733Iloczyn