zoukankan      html  css  js  c++  java
  • Version

    题目

    有三个操作:

    • (change u v a b) : (u)(v)路径上的点点权加上(a+k*b)(k)为第几个点,(u)为第0个点。
    • (query u v) : 询问(u)(v)路径上的点权和。
    • (roll w) : 回到第(w)(change)之后的状态。

    强制在线。

    分析

    会写树剖啦!会写树剖啦!会写树剖啦!
    当时没怎么看这题,一直在写前面的计算几何。其实这题也很简单,轻重链剖分加主席树即可。关键在于如何解决加上点权和查询的操作。我们发现加上的点权是一个等差数列。
    开始之考虑一个标记,(a)(b),那么如果一个区间是([l,r]),那么区间和为:

    [a * (r-l+1)+frac {b*(r-l)*(r-l+1)}{2} ]

    我们发现,标记的运算只和(l)(r)有关,并且同一个区间是一样的,于是对于每个区间,它的(a)(b)可以直接累加,标记不下传。
    写主席树的时候,可以给每个点打个标记,看看这个点是不是这一个时间点的,如果不是才新建。之前可持久化并查集也是一样的。

    代码

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cctype>
    #define open(x) (((x)+ans)%n+1)
    #define F(x) for (giant i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v)
    using namespace std;
    typedef long long giant;
    giant read() {
        giant x=0,f=1;
        char c=getchar();
        for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
        for (;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const giant maxn=1e5+10;
    const giant maxj=18;
    const giant nlogn=1<<23;
    giant n,last;
    giant ans=0,total=0;
    struct edge {
        giant v,nxt;
    } e[maxn<<1];
    giant h[maxn],tot=0,tim=0,root[maxn];
    void add(giant u,giant v) {
        e[++tot]=(edge){v,h[u]};
        h[u]=tot;
    }
    giant top[maxn],size[maxn],son[maxn],first[maxn],second[maxn],dfn=0;
    giant dep[maxn],father[maxn][maxj];
    giant tic[nlogn],tt=0;
    struct node {
        giant lc,rc,ta,tb,sum;
    } t[nlogn];
    giant lca(giant x,giant y) {
        if (dep[x]<dep[y]) swap(x,y);
        for (giant j=maxj-1;j>=0;--j) if (dep[father[x][j]]>=dep[y]) x=father[x][j];
        if (x==y) return x;
        for (giant j=maxj-1;j>=0;--j) if (father[x][j]!=father[y][j]) x=father[x][j],y=father[y][j];
        return father[x][0];
    }
    void dfs(giant x,giant fa) {
        size[x]=1;
        dep[x]=dep[fa]+1;
        father[x][0]=fa;
        giant ma=0,&id=son[x];
        F(x) if (v!=fa) {
            dfs(v,x);
            size[x]+=size[v];
            if (size[v]>ma) ma=size[v],id=v;
        }
    }
    void build(giant x,giant fa,giant tp) {
        if (!x) return;
        first[x]=++dfn;
        top[x]=tp;
        build(son[x],x,tp);
        F(x) if (v!=fa && v!=son[x]) build(v,x,v);
        second[x]=dfn;
    }
    void modify(giant &x,giant rt,giant L,giant R,giant l,giant r,giant thea,giant theb) {
        if (tic[x]!=tim) x=++tt,tic[x]=tim,t[x]=t[rt];
        if (L==l && R==r) {
            t[x].ta+=thea;
            t[x].tb+=theb;
            t[x].sum+=(R-L)*(R-L+1)/2*theb+(R-L+1)*thea;
            return;
        }
        giant mid=(L+R)>>1;
        if (r<=mid) modify(t[x].lc,t[rt].lc,L,mid,l,r,thea,theb); else
        if (l>mid) modify(t[x].rc,t[rt].rc,mid+1,R,l,r,thea,theb); else {
            modify(t[x].lc,t[rt].lc,L,mid,l,mid,thea,theb);
            modify(t[x].rc,t[rt].rc,mid+1,R,mid+1,r,thea+(mid-l+1)*theb,theb);
        }
        t[x].sum=t[t[x].lc].sum+t[t[x].rc].sum+(R-L)*(R-L+1)/2*t[x].tb+(R-L+1)*t[x].ta;
    }
    giant query(giant x,giant L,giant R,giant l,giant r) {
        if (L==l && R==r) return t[x].sum;
        giant len=r-l;
        giant ret=(2*t[x].ta+(l+r-L*2)*t[x].tb)*(r-l+1)/2;
        giant mid=(L+R)>>1;
        if (r<=mid) ret+=query(t[x].lc,L,mid,l,r); else
        if (l>mid) ret+=query(t[x].rc,mid+1,R,l,r); else {
            ret+=query(t[x].lc,L,mid,l,mid);
            ret+=query(t[x].rc,mid+1,R,mid+1,r);
        }
        return ret;
    }
    giant jump(giant x,giant y) {
        for (giant j=0;j<maxj;++j) if (y&(1<<j)) x=father[x][j];
        return x;
    }
    void change(giant u,giant v,giant a,giant b) {
        giant l=lca(u,v),utl=dep[u]-dep[l],x;
        for (x=u;dep[top[x]]>dep[l];x=father[top[x]][0]) {
            giant thea=a+b*(dep[u]-dep[top[x]]);
            giant theb=-b;
            modify(root[tim],last,1,n,first[top[x]],first[x],thea,theb);
        }
        if (dep[x]>=dep[l]) {
            giant thea=a+b*(dep[u]-dep[l]);
            giant theb=-b;
            modify(root[tim],last,1,n,first[l],first[x],thea,theb);
        } 
        for (x=v;dep[top[x]]>dep[l];x=father[top[x]][0]) {
            giant thea=a+b*(utl+dep[top[x]]-dep[l]);
            giant theb=b;
            modify(root[tim],last,1,n,first[top[x]],first[x],thea,theb);
        }
        if (dep[x]>dep[l]) {
            giant tmp=jump(x,dep[x]-dep[l]-1);
            giant thea=a+b*(utl+dep[tmp]-dep[l]);
            giant theb=b;
            modify(root[tim],last,1,n,first[tmp],first[x],thea,theb);
        }
        giant thea=a+utl*b,theb=-b;
    }
    giant ask(giant u,giant v) {
        giant l=lca(u,v),x,ret=0;
        for (x=u;dep[top[x]]>dep[l];x=father[top[x]][0]) {
            ret+=query(last,1,n,first[top[x]],first[x]);    
        }
        if (dep[x]>=dep[l]) {
            ret+=query(last,1,n,first[l],first[x]); 
        }
        for (x=v;dep[top[x]]>dep[l];x=father[top[x]][0]) {
            ret+=query(last,1,n,first[top[x]],first[x]);    
        }
        if (dep[x]>dep[l]) {
            int tmp=jump(x,dep[x]-dep[l]-1);
            ret+=query(last,1,n,first[tmp],first[x]);   
        }
        return ret;
    }
    void print(giant x) {
        if (!x) {
            puts("0");
            return;
        }
        static char s[20];
        int tot=0;
        while (x) s[++tot]=x%10+'0',x/=10;
        while (tot--) putchar(s[tot+1]);
        puts("");
    }
    int main() {
        #ifndef ONLINE_JUDGE
            freopen("test.in","r",stdin);
            freopen("my.out","w",stdout);
        #endif
        n=read();
        giant m=read();
        for (giant i=1;i<n;++i) {
            giant u=read(),v=read();
            add(u,v),add(v,u);
        }
        dfs(1,0);
        build(1,0,1);
        for (giant j=1;j<maxj;++j) for (giant i=1;i<=n;++i) father[i][j]=father[father[i][j-1]][j-1];
        int test=0;
        while (m--) {
            static char o[10];
            scanf("%s",o);
            if (o[0]=='c') {
                giant u=open(read()),v=open(read());
                giant a=read(),b=read();
                ++total,++tim;
                root[tim]=last;
                change(u,v,a,b);
                last=root[tim];
            } else if (o[0]=='q') {
                giant u=open(read()),v=open(read());
                ans=ask(u,v);
                print(ans);
            } else if (o[0]=='r') {
                last=root[(read()+ans)%(total+1)];  
            }
        }
    }
    
  • 相关阅读:
    053-98
    053-672
    053-675
    1031 Hello World for U (20分)
    1065 A+B and C (64bit) (20分)
    1012 The Best Rank (25分)
    1015 Reversible Primes (20分)
    1013 Battle Over Cities (25分)
    1011 World Cup Betting (20分)
    1004 Counting Leaves (30分)
  • 原文地址:https://www.cnblogs.com/owenyu/p/6724750.html
Copyright © 2011-2022 走看看