直接进行树链剖分,每次对路径区间内的所有点值+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; }