• [JLOI2014]松鼠的新家


    题目地址


    易错点:

    • 需要使用栈模拟递归
    • 不开O2无法通过

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<iostream>
    #include<stack>
    using namespace std;
    const int MAXN=1000010,MAXM=1000010;
    struct Node{
        int ls,rs,lazy;
        long long sum;
    }tr[MAXN];
    int nodeCnt=0;
    void insert(int &now,int l,int r,int ll,int rr,int x){
        if(!now)now=++nodeCnt;
        int b=min(r,rr)-max(l,ll)+1;
        tr[now].sum+=x*b;
        if(ll<=l&&rr>=r){
            tr[now].lazy+=x;
            return;
        }
        int mid=(l+r)>>1;
        if(ll<=mid)insert(tr[now].ls,l,mid,ll,rr,x);
        if(rr>mid)insert(tr[now].rs,mid+1,r,ll,rr,x);
    }
    long long query(int now,int l,int r,int ll,int rr){
        if(ll<=l&&rr>=r)return tr[now].sum;
        int mid=(l+r)>>1;
        if(tr[now].lazy){
            if(!tr[now].ls)tr[now].ls=++nodeCnt;
            tr[tr[now].ls].lazy+=tr[now].lazy;
            tr[tr[now].ls].sum+=tr[now].lazy*(mid-l+1);
            if(!tr[now].rs)tr[now].rs=++nodeCnt;
            tr[tr[now].rs].lazy+=tr[now].lazy;
            tr[tr[now].rs].sum+=tr[now].lazy*(r-mid);
            tr[now].lazy=0;
        }
        long long ans=0;
        if(ll<=mid)ans+=query(tr[now].ls,l,mid,ll,rr);
        if(rr>mid)ans+=query(tr[now].rs,mid+1,r,ll,rr);
        return ans;
    }
    struct Edge{
        int from,to,nxt;
    }e[MAXM];
    int head[MAXN],edgeCnt=1;
    void addEdge(int u,int v){
        e[++edgeCnt].from=u;
        e[edgeCnt].to=v;
        e[edgeCnt].nxt=head[u];
        head[u]=edgeCnt;
    }
    int dep[MAXN],fa[MAXN],son[MAXN],siz[MAXN];
    struct dfs_Node{
        int point;
        int type;
    };
    void dfs1(int x){
        stack<dfs_Node> s;
        s.push(dfs_Node{x,1});
        while(!s.empty()){
            dfs_Node nowNode=s.top();s.pop();
            int type=nowNode.type,nowPoint=nowNode.point;
            if(type==1){
                dep[nowPoint]=dep[fa[nowPoint]]+1;
        		siz[nowPoint]=1;
        		s.push(dfs_Node{nowPoint,2});
        		for(int i=head[nowPoint];i;i=e[i].nxt){
            		int nowV=e[i].to;
           			if(!dep[nowV]){
            			fa[nowV]=nowPoint;
             			s.push(dfs_Node{nowV,1});
            		}
        		}
            }else if(type==2){
                for(int i=head[nowPoint];i;i=e[i].nxt){
                    int nowV=e[i].to;
                    if(nowV==fa[nowPoint])continue;
             		siz[nowPoint]+=siz[nowV];
              		if(siz[nowV]>siz[son[nowPoint]])son[nowPoint]=nowV;
        		}
            }
        }
    }
    int id[MAXN],idCnt=0;
    int top[MAXN],root=0;
    void dfs2(int x){
        stack<dfs_Node> s;
        s.push(dfs_Node{x,0});
        while(!s.empty()){
            dfs_Node nowNode=s.top();s.pop();
            int nowPoint=nowNode.point,nowType=nowNode.type;
            if(nowType==0){
                id[nowPoint]=++idCnt;
                s.push(dfs_Node{nowPoint,1});
        		if(nowPoint==son[fa[nowPoint]])top[nowPoint]=top[fa[nowPoint]];
        		else top[nowPoint]=nowPoint;
        		if(son[nowPoint])s.push(dfs_Node{son[nowPoint],0});
            }else if(nowType==1){
                for(int i=head[nowPoint];i;i=e[i].nxt){
                    int nowV=e[i].to;
          			if(!id[nowV])s.push(dfs_Node{nowV,0});
                }
            }
        }
    }
    void modify(int u,int v,int x){
        while(top[u]!=top[v]){
            if(dep[top[u]]>dep[top[v]])swap(u,v);
            insert(root,1,MAXN,id[top[v]],id[v],x);
            v=fa[top[v]];
        }
        insert(root,1,MAXN,min(id[u],id[v]),max(id[u],id[v]),x);
    }
    long long sum(int u,int v){
        long long ans=0;
        while(top[u]!=top[v]){
            if(dep[top[u]]>dep[top[v]])swap(u,v);
            ans+=query(root,1,MAXN,id[top[v]],id[v]);
            v=fa[top[v]];
        }
        ans+=query(root,1,MAXN,min(id[u],id[v]),max(id[u],id[v]));
        return ans;
    }
    int read(){
        char c;int num,f=1;
        while(c=getchar(),!isdigit(c))if(c=='-')f=-1;num=c-'0';
        while(c=getchar(), isdigit(c))num=num*10+c-'0';
        return f*num;
    }
    int a[MAXN];
    int main(){
        //freopen("in.in","r",stdin);
        //freopen("out.out","w",stdout);
        int n;
        n=read();
        for(int i=1;i<=n;i++)
        	a[i]=read();
        for(int i=1;i<=n-1;i++){
            int x,y;
            x=read();y=read();
            addEdge(x,y);
            addEdge(y,x);
        }
        dfs1(1);
        dfs2(1);
        for(int i=1;i<=n-1;i++){
            modify(a[i],a[i+1],1);
            modify(a[i+1],a[i+1],-1);
        }
        for(int i=1;i<=n;i++){
        	printf("%lld
    ",query(root,1,MAXN,id[i],id[i]));
        }
        return 0;
    }
  • 相关阅读:
    产品设计理应遵循哪些原则?
    产品经理必读的九步法
    exec
    Class convert
    Connecting method
    ASP.NET读写操作
    Encrypt Decrypt
    EventHandler, EventArgs
    Convert using code
    Dictionary List
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680620.html
Copyright © 2020-2023  润新知