洛谷 P2147 [SDOI2008]洞穴勘测
以下这个做法应该是叫线段树分治。。。
根据修改操作预处理出每条边存在的时间区间[l,r](以操作序号为时间),然后把所有形式化后的修改挂到线段树节点上。
处理完修改后,dfs一遍线段树,进入某个节点时把那个点上所有的修改操作做一遍连边(用按秩合并并查集),出来时再撤销那些连边;那么到达叶节点时,刚好就是完成了这个节点代表的时间所需要的一切修改操作
复杂度O(nlog^2n),比lct要大
这个东西跟cdq分治一样是时间分治,但是好像不能降维的样子(?反正想了很久没想通),不过能在有些有加入、删除、查询操作的题中,把删除操作规避掉
以下代码把线段树避免掉了(其实是处理过程中把树建出来。。。)
1 #include<cstdio> 2 #include<algorithm> 3 #include<map> 4 #include<vector> 5 #define pb push_back 6 using namespace std; 7 struct Info 8 { 9 int fx,fy,dx,dy; 10 }ttt[4000100]; 11 int tlen; 12 struct Q 13 { 14 bool type; 15 int l,r,a,b; 16 }; 17 bool ans[200100]; 18 int qnum,n,m; 19 char tmp[10]; 20 map<int,int> ma[10100]; 21 map<int,int>::iterator it; 22 int fa[10100],dep[10100]; 23 int find(int x) 24 { 25 for(;x!=fa[x];x=fa[x]); 26 return x; 27 } 28 void add(const Q &x) 29 { 30 int fx=find(x.a),fy=find(x.b);++tlen; 31 ttt[tlen].fx=fx;ttt[tlen].fy=fy; 32 ttt[tlen].dx=dep[fx];ttt[tlen].dy=dep[fy]; 33 if(dep[fx]>dep[fy]) fa[fy]=fx; 34 else 35 { 36 fa[fx]=fy; 37 if(dep[fx]==dep[fy]) dep[fy]++; 38 } 39 } 40 void del(int tm) 41 { 42 for(int i=1,fx,fy;i<=tm;i++) 43 { 44 fx=ttt[tlen].fx;fy=ttt[tlen].fy; 45 fa[fx]=fx;fa[fy]=fy; 46 dep[fx]=ttt[tlen].dx;dep[fy]=ttt[tlen].dy; 47 --tlen; 48 } 49 } 50 void solve(const vector<Q> &q,int l,int r) 51 //当前线段树上区间为[l,r],要处理的询问为q 52 { 53 int i,nn=0,sz=q.size(); 54 if(l==r) 55 { 56 for(i=0;i<sz;i++) 57 if(q[i].type==0) 58 add(q[i]),++nn; 59 for(i=0;i<sz;i++) 60 if(q[i].type==1) 61 ans[l]=find(q[i].a)==find(q[i].b); 62 del(nn); 63 return; 64 } 65 int mid=l+(r-l)/2;vector<Q> qq1,qq2; 66 for(i=0;i<sz;i++) 67 { 68 if(q[i].type==0) 69 { 70 if(q[i].l<=l&&r<=q[i].r) add(q[i]),++nn; 71 else 72 { 73 if(q[i].l<=mid) qq1.push_back(q[i]); 74 if(mid<q[i].r) qq2.push_back(q[i]); 75 } 76 } 77 else 78 { 79 if(q[i].l<=mid) qq1.pb(q[i]); 80 else qq2.pb(q[i]); 81 } 82 } 83 solve(qq1,l,mid); 84 solve(qq2,mid+1,r); 85 del(nn); 86 } 87 vector<Q> q; 88 bool type[200100]; 89 int main() 90 { 91 int i,a,b; 92 scanf("%d%d",&n,&m); 93 for(i=1;i<=n;i++) fa[i]=i; 94 for(i=1;i<=m;i++) 95 { 96 scanf("%s%d%d",tmp,&a,&b);if(a>b) swap(a,b); 97 if(tmp[0]=='Q') q.pb((Q){1,i,0,a,b}),type[i]=1; 98 else if(tmp[0]=='C') ma[a][b]=i; 99 else if(tmp[0]=='D') q.pb((Q){0,ma[a][b],i,a,b}),ma[a].erase(b); 100 } 101 for(i=1;i<=n;i++) 102 for(it=ma[i].begin();it!=ma[i].end();it++) 103 q.pb((Q){0,it->second,m,i,it->first}); 104 solve(q,1,m); 105 for(i=1;i<=m;i++) 106 if(type[i]==1) 107 puts(ans[i]?"Yes":"No"); 108 return 0; 109 }