• 洛谷 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 }
  • 相关阅读:
    Wannafly挑战赛14 F.细胞
    D 勤奋的杨老师(二)(最小割)
    三分算法求最值
    初识最大流
    初识数据结构
    决策型DP
    哈希表
    【BZOJ】1878: [SDOI2009]HH的项链 (主席树)
    【HDU】1520 Anniversary party(树形dp)
    【UVa】1606 Amphiphilic Carbon Molecules(计算几何)
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9032165.html
Copyright © 2020-2023  润新知