JZOJ5662. [GDOI2018Day1 simulation 4.17] Chi shucunhong


The main idea of the topic

Give a binary tree,
There are left-hand and right-hand operations,
Ask for the product of the size of a subtree.

Title Solution

Balance trees have an important property:
No matter how you rotate, the middle order traversal of this tree will not change.
The subtree of a node is a continuous segment in the middle order traversal,
In other words, it requires that the middle order traverses the product of a certain continuous size in the middle.

Each rotation operation, whether left or right, will only change two points,
The size of two points, the left and right sons, and the interval of its subtree in the middle order traversal are modified each time,
Use line tree to maintain the product of size, single point modification and query interval.

code

#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 200003
#define M 103
#define db double
#define P putchar
#define G getchar
#define mo 1000000007
#define pi 3.1415926535897932384626433832795
using namespace std;
char ch;
void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    ll w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}

ll g[N*4],s[N];
int f[N],son[2][N],v[N],dfn[N],l[N],r[N];
int n,q,opt,x,id,opl,opr,ops,pos[N];

void build(int x,int l,int r) 
{
    if(l==r)
    {
        g[x]=s[dfn[l]];
        return;
    }
    int m=(l+r)>>1;
    build(x<<1,l,m);
    build((x<<1)|1,m+1,r);
    g[x]=g[x<<1]*g[(x<<1)|1]%mo;
}

void find(int x,int l,int r)
{
    if(opl<=l && r<=opr)
    {
        ops=ops*g[x]%mo;
        return;
    }
    int m=(l+r)>>1;
    if(opl<=m)find(x<<1,l,m);
    if(m<opr)find((x<<1)|1,m+1,r);
}

void work(int x,int l,int r)
{
    if(l==r)
    {
        g[x]=s[dfn[l]];
        return;
    }
    int m=(l+r)>>1;
    if(opl<=m)work(x<<1,l,m);
        else work((x<<1)|1,m+1,r);
    g[x]=g[x<<1]*g[(x<<1)|1]%mo;    
}

void rotate(int x,int w)//1:l 0:r
{   
    int y=son[w][x];
    if(!y)return;
    s[x]=(s[x]-s[y]+s[son[1-w][y]]+mo)%mo;
    s[y]=(s[x]+s[son[w][y]]+v[y]+mo)%mo;

    f[son[1-w][y]]=x;
    son[w][x]=son[1-w][y];
    f[y]=f[x];son[son[1][f[x]]==x?1:0][f[x]]=y;
    f[x]=y;son[1-w][y]=x;

    l[x]=son[0][x]?l[son[0][x]]:pos[x];r[x]=son[1][x]?r[son[1][x]]:pos[x];
    l[y]=son[0][y]?l[son[0][y]]:pos[y];r[y]=son[1][y]?r[son[1][y]]:pos[y];

    opl=pos[x];work(1,1,n);
    opl=pos[y];work(1,1,n);
}

void dfs(int x)
{
    if(!x)return;
    l[x]=id+1;
    dfs(son[0][x]);
    dfn[++id]=x;pos[x]=id;
    dfs(son[1][x]);
    r[x]=id;
}

int main()
{
    read(n);read(q);
    for(int i=1;i<=n;i++)
        read(v[i]),read(son[0][i]),read(son[1][i]),
            f[son[0][i]]=i,f[son[1][i]]=i;
    s[0]=f[0]=0;

    for(int i=n;i;i--)
        s[i]=(s[son[0][i]]+s[son[1][i]]+v[i])%mo;

    dfs(1);build(1,1,n);

    for(;q;q--)
    {
        read(opt);read(x);
        if(opt==2)
        {
            ops=1;opl=l[x];opr=r[x];
            find(1,1,n);
            write(ops);P('\n');
        }else rotate(x,opt);
    }

    return 0;
}

Posted by ole968 on Sun, 05 Apr 2020 12:50:10 -0700