• 【Luogu】P2146软件包管理器(树链剖分)


      题目链接

      上午跟rqy学了一道超难的概率题,准备颓一会,于是水了这么一道水题。

      话说这题真的是模板啊。数据范围正好,描述特别贴近(都不给你绕弯子的),连图都给你画出来,就差题目描述加一句“树链剖分模板”了qwq

      怕当年考noi的选手想不到这是树剖么qwq

      然后一般来讲省选及以上难度的题都是有套路的,也就是说你秒出的算法都过不了,比如轮状病毒肯定秒出高斯消元解行列式,然后就过不了了

      emm但是这个为什么是真的模板啊qwq

      我交之前还想着“没事,肯定被卡。我只看看我树剖暴力能拿几分”

      然后就A了啊喂。

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<cstdlib>
    #include<algorithm>
    #define maxn 300050
    #define left (rt<<1)
    #define right (rt<<1|1)
    #define mid ((l+r)>>1)
    #define lson l,mid,left
    #define rson mid+1,r,right
    using namespace std;
    
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    int n;
    int deep[maxn];
    int top[maxn];
    int father[maxn];
    int dfn[maxn],ID;
    int back[maxn];
    int size[maxn];
    int son[maxn];
    
    struct Edge{
        int next,to;
    }edge[maxn*3];
    int head[maxn],num;
    inline void add(int from,int to){
        edge[++num]=(Edge){head[from],to};
        head[from]=num;
    }
    
    void findfs(int x,int fa){
        deep[x]=deep[fa]+1;
        father[x]=fa;
        size[x]=1;
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(to==fa)    continue;
            findfs(to,x);
            size[x]+=size[to];
            if(son[x]==0||size[son[x]]<size[to])    son[x]=to;
        }
    }
    
    void unidfs(int x,int Top){
        dfn[x]=++ID;    back[ID]=1;
        top[x]=Top;
        if(!son[x])    return;
        unidfs(son[x],Top);
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(to==father[x]||to==son[x])    continue;
            unidfs(to,to);
        }
    }
    
    int tree[maxn*10],tag[maxn*10];
    
    inline void pushup(int rt){
        tree[rt]=tree[left]+tree[right];
    }
    
    void pushdown(int rt,int m){
        if(tag[rt]==-1)    return;
        tag[left]=tag[rt];
        tag[right]=tag[rt];
        tree[left]=tag[rt]*(m-(m>>1));
        tree[right]=tag[rt]*(m>>1);
        tag[rt]=-1;
        return;
    }
    
    void update(int from,int to,int num,int l,int r,int rt){
        if(from<=l&&to>=r){
            tree[rt]=num*(r-l+1);
            tag[rt]=num;
            return;
        }
        pushdown(rt,r-l+1);
        if(from<=mid)    update(from,to,num,lson);
        if(to>mid)        update(from,to,num,rson);
        pushup(rt);
        return;
    }
    
    void updatesum(int from,int to,int num){
        while(top[from]!=top[to]){
            if(deep[top[from]]<deep[top[to]])    swap(from,to);
            update(dfn[top[from]],dfn[from],num,1,n,1);
            from=father[top[from]];
        }
        if(deep[from]>deep[to])    swap(from,to);
        update(dfn[from],dfn[to],num,1,n,1);
        return;
    }
    
    int query(int from,int to,int l,int r,int rt){
        if(from<=l&&to>=r)    return tree[rt];
        int ans=0;
        pushdown(rt,r-l+1);
        if(from<=mid)    ans+=query(from,to,lson);
        if(to>mid)        ans+=query(from,to,rson);
        return ans;
    }
    
    int querysum(int from,int to){
        int ans=0;
        while(top[from]!=top[to]){
            if(deep[top[from]]<deep[top[to]])    swap(from,to);
            ans+=query(dfn[top[from]],dfn[from],1,n,1);
            from=father[top[from]];
        }
        if(deep[from]>deep[to])    swap(from,to);
        ans+=query(dfn[from],dfn[to],1,n,1);
        return ans;
    }
    
    void updatetree(int from,int num){
        update(dfn[from],dfn[from]+size[from]-1,num,1,n,1);
    }
    
    int querytree(int from){
        return query(dfn[from],dfn[from]+size[from]-1,1,n,1);
    }
    
    int main(){
        memset(tag,-1,sizeof(tag));
        n=read();
        for(int i=1;i<n;++i){
            int x=read();
            add(x+1,i+1);
            add(i+1,x+1);
        }
        findfs(1,1);
        unidfs(1,1);
        int m=read();
        for(int i=1;i<=m;++i){
            char ch[100];int x;
            scanf("%s%d",ch,&x);
            x++;
            if(ch[0]=='i'){
                int last=querysum(1,x);
                updatesum(1,x,1);
                int now=querysum(1,x);
                printf("%d
    ",now-last);
            }
            else{
                int last=querytree(x);
                updatetree(x,0);
                int now=querytree(x);
                printf("%d
    ",last-now);
            }
        }
        return 0;
    }
  • 相关阅读:
    CF1137FMatches Are Not a Child‘s Play【LCT】
    P4491[HAOI2018]染色【多项式,二项式反演】
    P3170[CQOI2015]标识设计【插头dp】
    log4j 使用教程说明
    log4j中Logger.getLogger()加载一个类提示错误
    编程基础 0x00008 的0x代表什么?
    编程基础 快速的进行 2进制,10进制,16进制 的 相互转换
    Java 基础 equals,hashcode和==的区别
    位运算 左移右移运算符 >>, <<, >>>
    Java 虚拟机 2.2 运行时数据区 Runtime Data Area
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8267259.html
Copyright © 2020-2023  润新知