zoukankan      html  css  js  c++  java
  • BZOJ 4285 使者 (CDQ分治+dfs序)

    题目传送门

    题目大意:给你一棵树,有三种操作,在两个点之间连一个传送门,拆毁一个已有的传送门,询问两个点之间的合法路径数量。一条合法路径满足 1.经过且仅经过一个传送门 2.不经过起点终点简单路径上的任何一条边

    这模型转化好神啊

    首先把树拍成$dfs$序

    问题是在树上,我们把$x,y$这条链拎出来摊平,那么链上每个点都挂了一些子树。

    容易发现合法路径数=连接以$x,y$为根的子树的传送门数量

    而无根树并没有“子树”这一概念,所以先随便挑一个根跑出来dfs序。

    发现“子树”的$dfs$序一定是一个或两个连续的区间,我们分$x,y$是否为$lca$讨论一下就可以了

    然后把问题放到二维坐标系上。

    问题转化成,动态在一个二维平面内加入/删除一个点,以及查询矩形内点的数量

    由于存在修改操作,需要再加上一维。那么整个问题变成了一个三维偏序问题。用$CDQ$分治+树状数组即可

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define N1 100005
      6 #define M1 500005
      7 #define ll long long 
      8 #define uint unsigned int 
      9 using namespace std;
     10  
     11 template <typename _T> void read(_T &ret)
     12 {
     13     ret=0; _T fh=1; char c=getchar();
     14     while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); }
     15     while(c>='0'&&c<='9'){ ret=ret*10+c-'0'; c=getchar(); }
     16     ret=ret*fh;
     17 }
     18  
     19 struct Edge{
     20 int to[N1*2],nxt[N1*2],head[N1],cte;
     21 void ae(int u,int v)
     22 { cte++; to[cte]=v; nxt[cte]=head[u]; head[u]=cte; }
     23 }e;
     24  
     25 int n;
     26  
     27 namespace Tree{
     28 int dep[N1],fa[N1],ff[N1][19],st[N1],ed[N1],ord[N1],cur;
     29 void dfs1(int x)
     30 {
     31     int j,v; ff[x][0]=x; st[x]=++cur; ord[cur]=x;//sz[x]=1; 
     32     for(j=e.head[x];j;j=e.nxt[j])
     33     {
     34         v=e.to[j]; if(v==fa[x]) continue;
     35         fa[v]=x; ff[v][1]=x; dep[v]=dep[x]+1;
     36         dfs1(v);
     37     }
     38     ed[x]=cur;
     39 }
     40 void init()
     41 { 
     42     dep[1]=1; dfs1(1); 
     43     int i,j;
     44     for(j=2;j<=18;j++)
     45     for(i=1;i<=n;i++)
     46         ff[i][j]=ff[ ff[i][j-1] ][j-1];
     47 }
     48 int LCA(int x,int y)
     49 {
     50     int i,ans=0;
     51     if(dep[x]<dep[y]) swap(x,y);
     52     for(i=18;i>=0;i--)
     53         if(dep[ff[x][i]]>=dep[y]) x=ff[x][i];
     54     if(x==y) return x;
     55     for(i=18;i>=0;i--)
     56         if(ff[x][i]==ff[y][i]) ans=ff[x][i];
     57         else x=ff[x][i], y=ff[y][i];
     58     return ans;
     59 }
     60 int LCB(int x,int D)
     61 {
     62     int i;
     63     for(i=18;i>=0;i--) 
     64         if(dep[ff[x][i]]>=D) x=ff[x][i];
     65     return x;
     66 }
     67 };
     68  
     69 struct BIT{
     70 int sum[N1];
     71 void upd(int x,int w)
     72 {
     73     if(!x) return; int i;
     74     for(i=x;i<=n;i+=(i&(-i)))
     75         sum[i]+=w;
     76 }
     77 int query(int x)
     78 {
     79     int ans=0,i;
     80     for(i=x;i>0;i-=(i&(-i)))
     81         ans+=sum[i];
     82     return ans;
     83 }
     84 void clr(int x)
     85 {
     86     int i;
     87     for(i=x;i<=n;i+=(i&(-i)))
     88         sum[i]=0;
     89 }
     90 }bit;
     91  
     92 struct OP{  int x,y,t,type,f; }op[M1],tmp[M1];
     93 int cmp2(OP &s1,OP &s2)
     94 { 
     95     if(s1.x!=s2.x) return s1.x<s2.x; 
     96     if(s1.y!=s2.y) return s1.y<s2.y;
     97     return s1.type<s2.type;
     98 }
     99 int ans[N1],que[M1],isquery[N1],tl;
    100  
    101 void CDQ(int L,int R)
    102 {
    103     if(L==R) return; 
    104     int M=(L+R)>>1,i,j,cnt=0;
    105     CDQ(L,M); CDQ(M+1,R);
    106     for(i=L,j=M+1;i<=M&&j<=R;)
    107     {
    108         if(cmp2(op[i],op[j])){
    109             if(!op[i].type) bit.upd(op[i].y,op[i].f), que[++tl]=op[i].y;
    110             tmp[++cnt]=op[i]; i++;
    111         }else{
    112             if(op[j].type) ans[op[j].t]+=op[j].f*bit.query(op[j].y);
    113             tmp[++cnt]=op[j]; j++;
    114         }
    115     }
    116     while(i<=M){ tmp[++cnt]=op[i]; i++; }
    117     while(j<=R){ tmp[++cnt]=op[j]; if(op[j].type) ans[op[j].t]+=op[j].f*bit.query(op[j].y); j++; }
    118     for(i=L;i<=R;i++) op[i]=tmp[i-L+1];
    119     while(tl){ bit.clr(que[tl]); tl--; }
    120 }
    121  
    122 int m,Q1,Q2;
    123 using Tree::st; using Tree::ed; using Tree::dep; using Tree::LCA; using Tree::LCB;
    124  
    125 int main()
    126 {
    127     scanf("%d",&n); 
    128     int i,j,x,y,z,F,q,fl;
    129     for(i=1;i<n;i++) read(x), read(y), e.ae(x,y), e.ae(y,x);
    130     Tree::init();
    131     read(Q1);
    132     for(q=1;q<=Q1;q++) 
    133     {
    134         read(x); read(y); 
    135         op[++m]=(OP){st[x],st[y],0,0,1}; op[++m]=(OP){st[y],st[x],0,0,1};
    136     }
    137     read(Q2);
    138     for(q=1;q<=Q2;q++) {
    139      
    140     read(fl); read(x); read(y);
    141     if(fl==1){
    142         op[++m]=(OP){st[x],st[y],q,0,1}; op[++m]=(OP){st[y],st[x],q,0,1};
    143     }else if(fl==2){
    144         op[++m]=(OP){st[x],st[y],q,0,-1}; op[++m]=(OP){st[y],st[x],q,0,-1};
    145     }else if(fl==3){
    146         F=LCA(x,y); isquery[q]=1;
    147         if(x==F||y==F){
    148             if(x==F) swap(x,y); z=LCB(x,dep[F]+1); 
    149             op[++m]=(OP){ed[x],st[z]-1,q,1,1};    //op[++m]=(OP){ed[x],0,q,1,-1};
    150             op[++m]=(OP){st[x]-1,st[z]-1,q,1,-1}; //op[++m]=(OP){st[x]-1,0,q,1,1};
    151             op[++m]=(OP){ed[x],n,q,1,1};    op[++m]=(OP){ed[x],ed[z],q,1,-1};
    152             op[++m]=(OP){st[x]-1,n,q,1,-1}; op[++m]=(OP){st[x]-1,ed[z],q,1,1};
    153         }else{
    154             op[++m]=(OP){ed[x],ed[y],q,1,1};    op[++m]=(OP){ed[x],st[y]-1,q,1,-1};
    155             op[++m]=(OP){st[x]-1,ed[y],q,1,-1}; op[++m]=(OP){st[x]-1,st[y]-1,q,1,1};   
    156         }
    157     }
    158      
    159     }
    160      
    161     CDQ(1,m);
    162     for(i=1;i<=Q2;i++) if(isquery[i])
    163         printf("%d
    ",ans[i]);
    164     return 0;
    165 }
  • 相关阅读:
    vue实践推荐
    angularjs实现checkbox的点击-全选功能-选中数据
    是你需要的前端编码风格吗?
    webpack--前端性能优化与Gzip原理
    基于verdaccio的npm私有仓库搭建
    使用uni-app开发微信小程序
    《JavaScript设计模式与开发实践》-- 迭代器模式
    《JavaScript设计模式与开发实践》-- 发布-订阅模式
    《JavaScript设计模式与开发实践》-- 策略模式
    《JavaScript设计模式与开发实践》-- 代理模式
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10603729.html
Copyright © 2011-2022 走看看