• 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:
    ",++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
    ",ans);
         }
      }
      return 0;
    }
  • 相关阅读:
    2-5
    2-3
    2-2
    2-1
    1-1
    实验6-1 求数组及其下标
    实验4-2 关于求阶乘的运算
    作业 3-5 switch语句的应用
    作业3-6 查询水果单价
    作业3-4 判断是不是闰年
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11567662.html
Copyright © 2020-2023  润新知