洛谷金秋夏令营模拟赛 第2场 T11738 伪神

Posted 友人A

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷金秋夏令营模拟赛 第2场 T11738 伪神相关的知识,希望对你有一定的参考价值。

 

调了一个下午只有八十分QAQ md弃了不管了 对拍也没拍出来 鬼知道是什么数据把我卡了QAQ

做法其实很简单 根据链剖的构造方法 你每次修改都是一段又一段的线段

那么你只要求一下线段并起来后哪些地方被覆盖了>=t次 不过要基数排序一波不然会T

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using std::swap;
using std::max;
const int N=450007,M=30000000,B=1024;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int n,m;
int first[N],cnt=1;
struct node{int to,next;}e[2*N];
void ins(int a,int b){e[++cnt]=(node){b,first[a]}; first[a]=cnt;}
void insert(int a,int b){ins(a,b); ins(b,a);}
int dep[N],top[N],sz[N],son[N],mx[N],fa[N],id[N],idp=1;
void f1(int x){
    sz[x]=1;
    for(int i=first[x];i;i=e[i].next){
        int now=e[i].to;
        if(now==fa[x]) continue;
        fa[now]=x; dep[now]=dep[x]+1;
        f1(now);sz[x]+=sz[now]; 
        if(sz[now]>sz[son[x]]) son[x]=now;
    }
}
void f2(int x,int tp){
    top[x]=tp; mx[x]=id[x]=idp++;
    if(son[x]) f2(son[x],tp),mx[x]=max(mx[x],mx[son[x]]);
    for(int i=first[x];i;i=e[i].next){
        int now=e[i].to;
        if(now!=fa[x]&&now!=son[x]) f2(now,now),mx[x]=max(mx[x],mx[now]);
    }
}
bool ly;
int a,b,t,cntq;
int f[2*M];
struct pos{int r,id,s;}q[M];
bool cmp(pos a,pos b){return a.r<b.r;}
void pcalc(){
    memset(f,0,sizeof(f));
    for(int i=0;i<cntq;i++) f[q[i].r]+=q[i].s;
    cntq=0;
}
void modify(int x,int y,int k){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        if(!ly){f[id[top[x]]]++; f[id[x]+1]--; x=fa[top[x]];continue;}
        q[cntq++]=(pos){id[top[x]],k,1};
        q[cntq++]=(pos){id[x]+1,k,-1};
        if(cntq>1e6&&ly){pcalc(); ly=false;}
        x=fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    if(!ly){f[id[x]]++; f[id[y]+1]--; return ;}
    q[cntq++]=(pos){id[x],k,1};
    q[cntq++]=(pos){id[y]+1,k,-1};
}
int T[1257];
pos *s[1257],*mp;
pos bb[M];
void jsort(int n){
    memset(T,0,sizeof(T)); mp=bb;
    for(int i=0;i<n;i++) ++T[q[i].r&1023];
    for(int i=0;i<B;i++) s[i]=mp,mp+=T[i];
    for(int i=0;i<n;i++) *s[q[i].r&1023]++=q[i];
    memset(T,0,sizeof(T)); mp=q;
    for(int i=0;i<n;i++) ++T[bb[i].r>>10];
    for(int i=0;i<B;i++) s[i]=mp,mp+=T[i];
    for(int i=0;i<n;i++) *s[bb[i].r>>10]++=bb[i];
}
int main(){
    int x,y;
    n=read(); m=read();
    for(int i=1;i<n;i++) x=read(),y=read(),insert(x,y);
    f1(1); f2(1,1);
    for(int i=1;i<=m;i++){
        a=read(); b=read(); t=read();
        cntq=0;
        ly=true;
        for(int j=1;j<=a;j++){
            x=read(); y=read();
            modify(x,y,i);
        }
        for(int j=1;j<=b;j++){
            x=read();
            if(!ly){f[id[x]]++; f[mx[x]+1]--;continue;}
            q[cntq++]=(pos){id[x],i,1};
            q[cntq++]=(pos){mx[x]+1,i,-1};
            if(cntq>1e6&&ly){pcalc(); ly=false;}
        }
        if(ly){
            jsort(cntq);
            bool f=false;
            int now=0,ans=0,last=0; 
            for(int j=0;j<cntq;j++){
                now+=q[j].s;
                if(f) ans=ans+(q[j].r-last);
                if(now<t) f=false;
                if(now>=t) f=true,last=q[j].r;
            }
            if(f&&last<=n) ans=ans+n-q[cntq-1].r+1;
            printf("%d\n",ans);
        }
        else{
            int now=0,ans=0;
            for(int j=1;j<=n;j++){
                now+=f[j];
                if(now>=t) ans++;
            }printf("%d\n",ans);
        }
    }
    return 0;
}
View Code

 

以上是关于洛谷金秋夏令营模拟赛 第2场 T11738 伪神的主要内容,如果未能解决你的问题,请参考以下文章

浴谷金秋线上集训营 T11738 伪神(树链剖分)

[周记]8.7~8.16

洛谷 U361 序列操作(NOIP模拟赛T2)

洛谷 U360 子矩阵 (NOIP模拟赛T1)题解

JSOI2018冬令营游记&总结(迁移自洛谷博客)

洛谷普及试炼场之旅