洛谷 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 }

 

posted @ 2018-05-13 15:04  hehe_54321  阅读(308)  评论(0编辑  收藏  举报
AmazingCounters.com