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)];  
        }
    }
}
posted @ 2017-04-17 20:41  permui  阅读(251)  评论(0编辑  收藏  举报