【BZOJ2759】一个动态树好题

来源:互联网 发布:php 活动报名 源代码 编辑:程序博客网 时间:2024/05/17 06:53

Description

有N个未知数x[1..n]和N个等式组成的同余方程组:
x[i]=k[i]*x[p[i]]+b[i] mod 10007
其中,k[i],b[i],x[i]∈[0,10007)∩Z
你要应付Q个事务,每个是两种情况之一:
一.询问当前x[a]的解
A a
无解输出-1
x[a]有多解输出-2
否则输出x[a]
二.修改一个等式
C a k[a] p[a] b[a]

Input

N
下面N行,每行三个整数k[i] p[i] b[i]
Q
下面Q行,每行一个事务,格式见题目描述

Output

对每个询问,输出一行一个整数。
对100%的数据,1≤N≤30000,0≤Q≤100000,时限2秒,其中询问事务约占总数的80%

Sample Input

5

2 2 1

2 3 2

2 4 3

2 5 4

2 3 5

5

A 1

A 2

C 5 3 1 1

A 4

A 5

Sample Output

4276

7141

4256

2126

HINT

Source

By 范浩强

确实是好题,就是不会做
看了Po姐姐的题解.Po姐题解,写得很详细.
主要就是这个题不是简单地树结构,可能成环,所以要多维护一个新的父亲节点,然后扩欧+LCT.

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define MAXN 30010#define P 10007#define GET (ch>='0'&&ch<='9')#define is_root(x) (tree[tree[x].fa].ch[0]!=x&&tree[tree[x].fa].ch[1]!=x)using namespace std;int n,q,dfn;int vis[MAXN],p[MAXN];int sta[MAXN],top;struct data{    int k,b;    friend data operator +(const data &x,const data &y) {   return (data){x.k*y.k%P,(x.b*y.k+y.b)%P};   }    int calc(int x) {   return (k*x+b)%P;   }};struct node {   int x,y;    };struct tree{    int ch[2],fa,fa2;    data val,sum;    bool rev;}tree[MAXN];inline void push_up(int x)  {   tree[x].sum=tree[tree[x].ch[0]].sum+tree[x].val+tree[tree[x].ch[1]].sum;    }inline void push_down(int x){    if (!x) return;    if (tree[x].rev)    {        tree[tree[x].ch[0]].rev^=1;tree[tree[x].ch[1]].rev^=1;        swap(tree[x].ch[0],tree[x].ch[1]);tree[x].rev^=1;    }}inline void rot(int x){    int y=tree[x].fa,z=tree[y].fa,l=(tree[y].ch[1]==x),r=l^1;    if (!is_root(y))    tree[z].ch[tree[z].ch[1]==y]=x;    tree[y].fa=x;tree[tree[x].ch[r]].fa=y;tree[x].fa=z;    tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y;    push_up(y);push_up(x);}inline void Splay(int x){    top=0;sta[++top]=x;    for (int i=x;!is_root(i);i=tree[i].fa)  sta[++top]=tree[i].fa;    while (top) push_down(sta[top--]);    while (!is_root(x))    {        int y=tree[x].fa,z=tree[y].fa;        if (!is_root(y))        {            if ((tree[y].ch[0]==x)^(tree[z].ch[0]==y))  rot(x);            else    rot(y);        }        rot(x);    }}inline void access(int x)   {   for (int i=0;x;i=x,x=tree[x].fa)    Splay(x),tree[x].ch[1]=i,push_up(x);    }inline void make_root(int x)    {   access(x);Splay(x);tree[x].rev^=1;  }inline void link(int x,int y)   {   make_root(x);tree[x].fa=y;  }inline void cut(int x,int y)    {   make_root(x);access(y);Splay(y);tree[x].fa=tree[y].ch[0]=0;push_up(y);  }inline void split(int x,int y)  {   make_root(x);access(y);Splay(y);    }inline int find_root(int x) {   for (access(x),Splay(x);tree[x].ch[0];x=tree[x].ch[0]);return x;    }node exgcd(int x,int y){    if  (!y)    return (node){1,0};    node t=exgcd(y,x%y);return (node){t.y,t.x-x/y*t.y};}inline int inv(int x)   {   return (exgcd((x+P)%P,P).x+P)%P;    }inline int query(int x){    int root=find_root(x);    access(tree[root].fa2);Splay(tree[root].fa2);    int k=tree[tree[root].fa2].sum.k,b=tree[tree[root].fa2].sum.b;    if (k==1)   return b==0?-2:-1;    int tmp=(P-b)*inv(k-1)%P;    access(x);Splay(x);return tree[x].sum.calc(tmp);}inline void modify(int x,int k,int b,int f){    int root=find_root(x);    tree[x].val.k=k;tree[x].val.b=b;push_up(x);    if (x==root)    tree[x].fa2=0;    else    {        access(x);Splay(x);        tree[tree[x].ch[0]].fa=0;tree[x].ch[0]=0;        push_up(x);        if (find_root(tree[root].fa2)!=root)            access(root),Splay(root),            tree[root].fa=tree[root].fa2,tree[root].fa2=0;    }    access(x);Splay(x);    if (find_root(f)==x)    tree[x].fa2=f;    else    tree[x].fa=f;}void dfs(int x){    vis[x]=dfn;    if (vis[p[x]]==dfn) {   tree[x].fa2=p[x];return;    }    tree[x].fa=p[x];    if (!vis[p[x]]) dfs(p[x]);}inline void in(int &x){    char ch=getchar();x=0;    while (!GET)    ch=getchar();    while (GET) x=x*10+ch-'0',ch=getchar();}int main(){    in(n);int x,k,f,b;char ch[3];    tree[0].val.k=tree[0].sum.k=1;tree[0].val.b=tree[0].sum.b=0;    for (int i=1;i<=n;i++)          in(k),in(f),in(b),p[i]=f,        tree[i].val.k=k,tree[i].val.b=b,        tree[i].sum.k=k,tree[i].sum.b=b;    for (int i=1;i<=n;i++)  if (!vis[i])    ++dfn,dfs(i);    for (in(q);q;q--)    {        scanf("%s",ch);        if (ch[0]=='A') in(x),printf("%d\n",query(x));        else    in(x),in(k),in(f),in(b),modify(x,k,b,f);    }}
2 0