20182019-acmicpc-asia-dhaka-regional F .Path Intersection 樹鏈剖分

直接進行樹鏈剖分,每次對路徑區間內的所有點值+1,線段樹進行維護,然後查詢線段樹的最大值的個數!!!

查詢線段樹區間最大值個數,可以先維護區間和,在維護區間最值,如果區間和等於區間最值乘以區間長度,那麼直接返回長度!!!

清空的時候,直接減去,不要直接重新建樹

#include<bits/stdc++.h>
#define LL long long
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const int MAXN = 2e5+6;
struct node{
  int l,r;
  int sum,laze;
  int maxx;
}tree[MAXN<<2];
struct edge{
   int Next,to;
}e[MAXN<<1];
int head[MAXN];
int siz[MAXN];
int top[MAXN];
int son[MAXN];
int d[MAXN];
int fa[MAXN];
int id[MAXN];
int sz[MAXN];
int uu[55],vv[55];
int cnt,tot;
void add(int x,int y){
   e[++tot].Next=head[x];
   e[tot].to=y;
   head[x]=tot;
}
void dfs1(int u,int f,int depth){
   d[u]=depth;
   fa[u]=f;
   siz[u]=1;
   for (int i=head[u];i;i=e[i].Next){
     int v=e[i].to;
     if (v==f)
        continue;
     dfs1(v,u,depth+1);
     siz[u]+=siz[v];
     if (siz[v]>siz[son[u]])
        son[u]=v;
   }
}
void dfs2(int u,int t){
    top[u]=t;
    id[u]=++cnt;
    if (!son[u])
        return;
    dfs2(son[u],t);
    for (int i=head[u];i;i=e[i].Next)
    {
        int v=e[i].to;
        if (v!=son[u] && v!=fa[u])
            dfs2(v,v);
    }
}
void push_down(int rt){
    if (tree[rt].laze){
       tree[lson].sum+=(tree[lson].r-tree[lson].l+1)*tree[rt].laze;
       tree[rson].sum+=(tree[rson].r-tree[rson].l+1)*tree[rt].laze;
       tree[lson].maxx+=tree[rt].laze;
       tree[rson].maxx+=tree[rt].laze;
       tree[lson].laze+=tree[rt].laze;
       tree[rson].laze+=tree[rt].laze;
       tree[rt].laze=0;
    }
}
void buildtree(int rt,int l,int r){
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].sum=0;
    tree[rt].laze=0;
    tree[rt].maxx=0;
    int mid=(l+r)>>1;
    if (l==r){
        return;
    }
    buildtree(lson,l,mid);
    buildtree(rson,mid+1,r);
}
void update(int rt,int ul,int ur,int w){
   if (ul>ur)return;
   int l=tree[rt].l;
   int r=tree[rt].r;
   if (ul<=l && r<=ur){
     tree[rt].laze+=w;
     tree[rt].maxx+=w;
     tree[rt].sum+=(r-l+1)*w;
     return;
   }
   push_down(rt);
   int mid=(l+r)>>1;
   if (ur<=mid){
     update(lson,ul,ur,w);
   }else if (ul>mid){
     update(rson,ul,ur,w);
   }else {
     update(lson,ul,ur,w);
     update(rson,ul,ur,w);
   }
   tree[rt].maxx=max(tree[lson].maxx,tree[rson].maxx);
   tree[rt].sum=tree[lson].sum+tree[rson].sum;
}
void qRange(int x,int y,int k){
    while(top[x]!=top[y]){
        if (d[top[x]]<d[top[y]])swap(x,y);
        update(1,id[top[x]],id[x],k);
        x=fa[top[x]];
    }
    if (d[x]>d[y])swap(x,y);
    update(1,id[x],id[y],k);
}
int query(int rt,int ql,int qr,int w){
    int l=tree[rt].l;
    int r=tree[rt].r;
    if (tree[rt].sum==w*(r-l+1)){
        return r-l+1;
    }
    if (l==r){
        return 0;
    }
    push_down(rt);
    int mid=(l+r)>>1;
    int ans=0;
    if (tree[lson].maxx==w){
       ans+=query(lson,ql,qr,w);
    }
    if (tree[rson].maxx==w){
        ans+=query(rson,ql,qr,w);
    }
    return ans;
}
int main(){
  int t;
  scanf("%d",&t);
  int n;
  int ca=0;
  while(t--){
     memset(head,0,sizeof(head));
     memset(id,0,sizeof(id));
     memset(top,0,sizeof(top));
     memset(siz,0,sizeof(siz));
     memset(fa,0,sizeof(fa));
     memset(son,0,sizeof(son));
     memset(d,0,sizeof(d));
     scanf("%d",&n);
     cnt=0;
     tot=0;
     int u,v;
     for (int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
     }
     int r,op,k;
     dfs1(1,0,1);
     dfs2(1,1);
     scanf("%d",&op);
     printf("Case %d:\n",++ca);
     buildtree(1,1,n);
     for (int i=1;i<=op;i++){
       scanf("%d",&k);
       for (int i=1;i<=k;i++){
          scanf("%d%d",&uu[i],&vv[i]);
          qRange(uu[i],vv[i],1);
       }
       int ans=query(1,1,n,k);
       for (int i=1;i<=k;i++){
          qRange(uu[i],vv[i],-1);
       }
       printf("%d\n",ans);
     }
  }
  return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章