zoukankan      html  css  js  c++  java
  • BZOJ 3091: 城市旅行 [LCT splay 期望]

    3091: 城市旅行

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1454  Solved: 483
    [Submit][Status][Discuss]

    Description

    Input

    Output

    Sample Input

    4 5
    1 3 2 5
    1 2
    1 3
    2 4
    4 2 4
    1 2 4
    2 3 4
    3 1 4 1
    4 1 4

    Sample Output

    16/3
    6/1

    HINT

    对于所有数据满足 1<=N<=50,000 1<=M<=50,000 1<=Ai<=10^6 1<=D<=100 1<=U,V<=N

    Source

    wyx528命题


    谜一般的翻转标记

    大爷题解传送门:http://blog.csdn.net/popoqqq/article/details/40823659

    与上一题不一样的是,每个点在链上的位置不一定,所以没法维护vi*i之类的东西,只能像那样记录lsum和rsum然后update的时候处理

    本题的翻转标记必须立即生效,因为反转标记还会影响lsum和rsum

    除了一开始就Link外,还可以保存图然后dfs只设置fa关系不用Link,然而并没有带来常数提升反而更慢了...

    BZOJ 100题达成

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define pa t[x].fa
    #define lc t[x].ch[0]
    #define rc t[x].ch[1]
    const int N=5e4+5;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    struct node{
        int ch[2],fa,rev;
        ll add,lsum,rsum,sum,exp,w,size;
    }t[N];
    inline int wh(int x){return t[pa].ch[1]==x;}
    inline int isRoot(int x){return t[pa].ch[0]!=x&&t[pa].ch[1]!=x;}
    inline void update(int x){
        t[x].size=t[lc].size+t[rc].size+1;
        t[x].sum=t[lc].sum+t[rc].sum+t[x].w;
        t[x].lsum=t[lc].lsum+t[x].w*(t[lc].size+1)+t[rc].lsum+t[rc].sum*(t[lc].size+1);
        t[x].rsum=t[rc].rsum+t[x].w*(t[rc].size+1)+t[lc].rsum+t[lc].sum*(t[rc].size+1);
        t[x].exp=t[lc].exp+t[rc].exp
        +t[lc].lsum*(t[rc].size+1)+t[rc].rsum*(t[lc].size+1)
        +t[x].w*(t[lc].size+1)*(t[rc].size+1);
    }
    inline ll cal1(ll x){return x*(x+1)/2;}
    inline ll cal2(ll x){return x*(x+1)*(x+2)/6;}
    inline void paint(int x,ll d){
        t[x].w+=d;
        t[x].add+=d;
        t[x].sum+=d*t[x].size;
        t[x].lsum+=d*cal1(t[x].size);
        t[x].rsum+=d*cal1(t[x].size);
        t[x].exp+=d*cal2(t[x].size);
    }
    inline void rever(int x){
        swap(lc,rc);
        swap(t[x].lsum,t[x].rsum);
        t[x].rev^=1;
    }
    inline void pushDown(int x){
        if(t[x].rev){
            rever(lc);
            rever(rc);//!!!!!
            t[x].rev=0;
        }
        if(t[x].add){
            paint(lc,t[x].add);
            paint(rc,t[x].add);
            t[x].add=0;
        }
    }
    
    inline void rotate(int x){
        int f=t[x].fa,g=t[f].fa,c=wh(x);
        if(!isRoot(f)) t[g].ch[wh(f)]=x;t[x].fa=g;
        t[f].ch[c]=t[x].ch[c^1];t[t[f].ch[c]].fa=f;
        t[x].ch[c^1]=f;t[f].fa=x;
        update(f);update(x);
    }
    int st[N],top;
    inline void splay(int x){
        top=0;st[++top]=x;
        for(int i=x;!isRoot(i);i=t[i].fa) st[++top]=t[i].fa;
        for(int i=top;i>=1;i--) pushDown(st[i]);
        
        for(;!isRoot(x);rotate(x))
            if(!isRoot(pa)) rotate(wh(x)==wh(pa)?pa:x);
    }
    
    inline void Access(int x){
        for(int y=0;x;y=x,x=pa){
            splay(x);
            rc=y;
            update(x);
        }
    }
    inline void MakeR(int x){
        Access(x);splay(x);
        rever(x);
    }
    inline int FindR(int x){
        Access(x);splay(x);
        while(lc) x=lc;
        return x;
    }
    inline void Link(int x,int y){
        MakeR(x);
        t[x].fa=y;
    }
    inline void Cut(int x,int y){
        MakeR(x);Access(y);splay(y);
        t[y].ch[0]=t[x].fa=0;
        update(y);//!!!
    }
    inline void Add(int x,int y,int d){
        if(FindR(x)!=FindR(y)) return;
        MakeR(x);Access(y);splay(y);
        paint(y,d);
    }
    inline ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
    inline void Que(int x,int y){
        if(FindR(x)!=FindR(y)){puts("-1");return;}
        MakeR(x);Access(y);splay(y);
        ll a=t[y].exp,b=t[y].size*(t[y].size+1)/2;
        ll g=gcd(a,b);//printf("Que %d %d %d
    ",a,b,g);
        printf("%lld/%lld
    ",a/g,b/g);
    }
    int n,Q,a,op,x,y,d;
    int main(){
        n=read();Q=read();
        for(int i=1;i<=n;i++){
            a=read();
            t[i].size=1;
            t[i].w=t[i].lsum=t[i].rsum=t[i].sum=t[i].exp=a;
        }
        for(int i=1;i<=n-1;i++) x=read(),y=read(),Link(x,y);
        while(Q--){
            op=read();x=read();y=read();
            if(op==1) if(FindR(x)==FindR(y)) Cut(x,y);
            if(op==2) if(FindR(x)!=FindR(y)) Link(x,y);
            if(op==3) d=read(),Add(x,y,d);
            if(op==4) Que(x,y);
        }
    }
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define pa t[x].fa
    #define lc t[x].ch[0]
    #define rc t[x].ch[1]
    const int N=5e4+5;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    struct node{
        int ch[2],fa,rev;
        ll add,lsum,rsum,sum,exp,w,size;
    }t[N];
    inline int wh(int x){return t[pa].ch[1]==x;}
    inline int isRoot(int x){return t[pa].ch[0]!=x&&t[pa].ch[1]!=x;}
    inline void update(int x){
        t[x].size=t[lc].size+t[rc].size+1;
        t[x].sum=t[lc].sum+t[rc].sum+t[x].w;
        t[x].lsum=t[lc].lsum+t[x].w*(t[lc].size+1)+t[rc].lsum+t[rc].sum*(t[lc].size+1);
        t[x].rsum=t[rc].rsum+t[x].w*(t[rc].size+1)+t[lc].rsum+t[lc].sum*(t[rc].size+1);
        t[x].exp=t[lc].exp+t[rc].exp
        +t[lc].lsum*(t[rc].size+1)+t[rc].rsum*(t[lc].size+1)
        +t[x].w*(t[lc].size+1)*(t[rc].size+1);
    }
    inline ll cal1(ll x){return x*(x+1)/2;}
    inline ll cal2(ll x){return x*(x+1)*(x+2)/6;}
    inline void paint(int x,ll d){
        t[x].w+=d;
        t[x].add+=d;
        t[x].sum+=d*t[x].size;
        t[x].lsum+=d*cal1(t[x].size);
        t[x].rsum+=d*cal1(t[x].size);
        t[x].exp+=d*cal2(t[x].size);
    }
    inline void rever(int x){
        swap(lc,rc);
        swap(t[x].lsum,t[x].rsum);
        t[x].rev^=1;
    }
    inline void pushDown(int x){
        if(t[x].rev){
            rever(lc);
            rever(rc);//!!!!!
            t[x].rev=0;
        }
        if(t[x].add){
            paint(lc,t[x].add);
            paint(rc,t[x].add);
            t[x].add=0;
        }
    }
    
    inline void rotate(int x){
        int f=t[x].fa,g=t[f].fa,c=wh(x);
        if(!isRoot(f)) t[g].ch[wh(f)]=x;t[x].fa=g;
        t[f].ch[c]=t[x].ch[c^1];t[t[f].ch[c]].fa=f;
        t[x].ch[c^1]=f;t[f].fa=x;
        update(f);update(x);
    }
    int st[N],top;
    inline void splay(int x){
        top=0;st[++top]=x;
        for(int i=x;!isRoot(i);i=t[i].fa) st[++top]=t[i].fa;
        for(int i=top;i>=1;i--) pushDown(st[i]);
        
        for(;!isRoot(x);rotate(x))
            if(!isRoot(pa)) rotate(wh(x)==wh(pa)?pa:x);
    }
    
    inline void Access(int x){
        for(int y=0;x;y=x,x=pa){
            splay(x);
            rc=y;
            update(x);
        }
    }
    inline void MakeR(int x){
        Access(x);splay(x);
        rever(x);
    }
    inline int FindR(int x){
        Access(x);splay(x);
        while(lc) x=lc;
        return x;
    }
    inline void Link(int x,int y){
        MakeR(x);
        t[x].fa=y;
    }
    inline void Cut(int x,int y){
        MakeR(x);Access(y);splay(y);
        t[y].ch[0]=t[x].fa=0;
        update(y);//!!!
    }
    inline void Add(int x,int y,int d){
        if(FindR(x)!=FindR(y)) return;
        MakeR(x);Access(y);splay(y);
        paint(y,d);
    }
    inline ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
    inline void Que(int x,int y){
        if(FindR(x)!=FindR(y)){puts("-1");return;}
        MakeR(x);Access(y);splay(y);
        ll a=t[y].exp,b=t[y].size*(t[y].size+1)/2;
        ll g=gcd(a,b);//printf("Que %d %d %d
    ",a,b,g);
        printf("%lld/%lld
    ",a/g,b/g);
    }
    int n,Q,a,op,x,y,d;
    
    struct edge{
        int v,ne;
    }e[N<<1];
    int cnt,h[N];
    inline void ins(int u,int v){
        cnt++;
        e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
    }
    inline void dfs(int u,int fa){
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].v!=fa){
                t[e[i].v].fa=u;
                dfs(e[i].v,u);
            }
    }
    int main(){
        n=read();Q=read();
        for(int i=1;i<=n;i++){
            a=read();
            t[i].size=1;
            t[i].w=t[i].lsum=t[i].rsum=t[i].sum=t[i].exp=a;
        }
        for(int i=1;i<=n-1;i++) x=read(),y=read(),ins(x,y);
        dfs(1,0);
        while(Q--){
            op=read();x=read();y=read();
            if(op==1) if(FindR(x)==FindR(y)) Cut(x,y);
            if(op==2) if(FindR(x)!=FindR(y)) Link(x,y);
            if(op==3) d=read(),Add(x,y,d);
            if(op==4) Que(x,y);
        }
    }
  • 相关阅读:
    Windows Intune, 让企业 IT 如履平地
    如何利用 WinDbg 进行双机调试
    微软 Windows Intune 云托管服务试用
    如何安装从 Windows Update 目录下载的驱动程序
    启用特殊池解读 0x000000c5 蓝屏
    C# 配置文件修改的新方法
    Ribbon默认服务器功能区自定义位置
    Update list item using Linq to SharePoint
    TroubleShoot:分配对象查询的问题
    TroubleShoot:C#操作Excel的几个问题
  • 原文地址:https://www.cnblogs.com/candy99/p/6275754.html
Copyright © 2011-2022 走看看