jzoj 5662. 【GDOI2018Day1模拟4.17】尺树寸泓

原创 2018年04月17日 21:00:12

题目大意:

这里写图片描述

思路:

平衡树很简单了,学过的大概多知道,推一推会发现,他的sum是和只有旋转点会变,mul所有的父亲都会变,在多次旋转后可能为一条链,那么时间复杂度就会爆炸。
这时我们可以先求出中序遍历,那么平衡树的点在中序遍历中的相对位置不会变。子树也在包含他的连续区间里面。这样就只用维护每个点的sum值,然后区间乘法求出mul的值。

程序:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define mo 1000000007
#define N 2000005
#define LL long long
using namespace std;
struct data{int l,r;}son[N];
LL f[N],sum[N],a[N],fa[N],size[N],b[N],c[N];
int n,q,opt,x,s;
LL ans;
struct tree{int l,r; LL mul;}t[N*4];
int dfs(int x){
    size[x]=1;
    if (son[x].l) dfs(son[x].l);
    b[++s]=x;
    c[x]=s;
    if (son[x].r) dfs(son[x].r);
    sum[x]=(sum[son[x].l]+sum[son[x].r]+a[x])%mo;
    f[x]=((f[son[x].l]*f[son[x].r])%mo*sum[x])%mo;
    size[x]+=size[son[x].l]+size[son[x].r];
}

void ins(int rt,int l,int r){
    t[rt].l=l; t[rt].r=r;
    if (l==r){
        t[rt].mul=sum[b[l]];
        return;
    }
    int mid=(l+r)/2;
    ins(rt*2,l,mid);
    ins(rt*2+1,mid+1,r);
    t[rt].mul=(t[rt*2].mul*t[rt*2+1].mul)%mo;
}

void change(int rt,int l,int r,int x,int y){
    if (l==r){
        t[rt].mul=y;
        return;
    }
    int mid=(l+r)/2;
    if (mid>=x) change(rt*2,l,mid,x,y);
            else change(rt*2+1,mid+1,r,x,y);
    t[rt].mul=(t[rt*2].mul*t[rt*2+1].mul)%mo;   
}

void mul(int rt, int l,int r,int x,int y){
    if (l==x&&r==y) {
        ans*=t[rt].mul;
        ans=ans%mo; 
        return;
    };
    int mid=(l+r)/2;
    if (y<=mid)  mul(rt*2,l,mid,x,y);
    else if (x>mid)  mul(rt*2+1,mid+1,r,x,y);
    else  mul(rt*2,l,mid,x,mid),mul(rt*2+1,mid+1,r,mid+1,y);;
}

int rrotate(int x){
    int y=son[x].l;
    if (son[fa[x]].l==x) son[fa[x]].l=y;
                    else son[fa[x]].r=y;
    int u=size[y];
    size[y]=size[x];
    size[x]=size[x]-u+size[son[y].r];
    fa[son[y].r]=x;
    fa[y]=fa[x];
    fa[x]=y;
    son[x].l=son[y].r;
    son[y].r=x;
    sum[x]=(sum[son[x].l]+sum[son[x].r]+a[x])%mo;
    change(1,1,n,c[x],sum[x]);
    sum[y]=(sum[son[y].l]+sum[son[y].r]+a[y])%mo;
    change(1,1,n,c[y],sum[y]);
}

int lrotate(int x){
    int y=son[x].r;
    if (son[fa[x]].l==x) son[fa[x]].l=y;
                    else son[fa[x]].r=y;
    int u=size[y];
    size[y]=size[x];
    size[x]=size[x]-u+size[son[y].l];
    fa[son[y].l]=x;
    fa[y]=fa[x];
    fa[x]=y;
    son[x].r=son[y].l;
    son[y].l=x;
    sum[x]=(sum[son[x].l]+sum[son[x].r]+a[x])%mo;
    change(1,1,n,c[x],sum[x]);
    sum[y]=(sum[son[y].l]+sum[son[y].r]+a[y])%mo;
    change(1,1,n,c[y],sum[y]);
}



int main(){
    freopen("splay.in","r",stdin);
    freopen("splay.out","w",stdout);
    scanf("%d%d",&n,&q);
    f[0]=1;
    for (int i=1;i<=n;i++){
        scanf("%d%d%d",&a[i],&son[i].l,&son[i].r);
        f[i]=1;
        fa[son[i].l]=i;
        fa[son[i].r]=i;
    }
    for (int i=0;i<N;i++)
     t[i].mul=1;
    dfs(1);
    ins(1,1,n);
    for (int i=1;i<=q;i++){
        scanf("%d%d",&opt,&x);
        if (opt==0) if (son[x].l) rrotate(x);
        if (opt==1) if (son[x].r) lrotate(x);
        if (opt==2) {
            ans=1;
            mul(1,1,n,c[x]-size[son[x].l],c[x]+size[son[x].r]);
            printf("%lld\n",ans);
        }
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq872425710/article/details/79980728

android 动态库死机调试方法

android 动态库死机调试方法 分类: Android学习2011-12-15 17:47 367人阅读 评论(0) 收藏 举报 这两种方法都不是我发明了,都是网上一些高手...
  • manshq163com
  • manshq163com
  • 2012-05-24 17:39:13
  • 331

jzoj 5661. 【GDOI2018Day1模拟4.17】药香沁鼻 dp

DescriptionInputOutputSample Input6 9 1 1 1 1 1 100 8 1 1 1 3 6 2 3 1000 4 1 4Sample Output105...
  • liangzihao1
  • liangzihao1
  • 2018-04-17 14:41:00
  • 15

jzoj5662 [GDOI2018Day1模拟4.17]尺树寸泓

Description 给定一棵splay,每个节点都有一个权值,节点x的价值为以x为根的子树中所有节点的权值和 分别有一下三种操作: 0 x:将x节点左旋 1 x:将x节点右旋 2 x...
  • jpwang8
  • jpwang8
  • 2018-04-17 21:03:49
  • 7

jzoj 5661. 【GDOI2018Day1模拟4.17】药香沁鼻

题目大意: 思路: 因为选y一定要先选x,所以这是一题0.1分数规划的树形依赖背包。(比较懒) 先用dfs把树转化成序列,如果cnt&amp;gt;W[I]那么就是可以装下的那么当先点的...
  • qq872425710
  • qq872425710
  • 2018-04-17 20:43:37
  • 10

jzoj5663 [GDOI2018Day1模拟4.17]呼吸决定

Description 这次的题意出奇短 求∑i=1nμ(i)im∑i=1nμ(i)im\sum_{i=1}^{n}\mu(i)i^m 已知1≤n≤1091≤n≤1091\leq n\leq...
  • jpwang8
  • jpwang8
  • 2018-04-18 08:12:14
  • 1

【GDOI2018Day1模拟4.17】药香沁鼻

题目 分析 首先求出这棵树的dfs序,设lx表示以x为根的子树中的dfs序最小值(即点x的dfs序),设rx表示以x为根的子树中的dfs序最大值。 然后按照dfs序枚举点,每个点维护一个背包...
  • A_loud_name
  • A_loud_name
  • 2018-04-17 18:54:57
  • 7

JZOJ 7.10B组第一题 可见点数

题目: ZPS经过长期的努力争取,终于成为了0901班的领操员,他要带领0901班参加广播操比赛。现在0901班的队伍可以看作是一个n*n的点阵,每个人都站在格点上。现在作为领操员的ZPS站(0,0...
  • qq_34510600
  • qq_34510600
  • 2017-07-10 20:17:22
  • 67

[JZOJ5402]【NOIP2017提高A组模拟10.8】God Knows (口胡)

Description Solution设f[i]f[i]表示前i个点已经被解决了,并且第i个点选,最小代价。 那么可以考虑转移 f[i]=min(f[j]+c[i]),j...
  • hzj1054689699
  • hzj1054689699
  • 2017-10-17 16:42:46
  • 232

JZOJ5498. 【清华集训2017模拟12.10】大佬的难题

大佬的难题
  • lijf2001
  • lijf2001
  • 2017-12-14 17:05:52
  • 78

JZOJ 4777. 【NOIP2016提高A组模拟9.14】灌水

纯模拟
  • huangjingyuan107
  • huangjingyuan107
  • 2016-11-13 22:02:57
  • 220
收藏助手
不良信息举报
您举报文章:jzoj 5662. 【GDOI2018Day1模拟4.17】尺树寸泓
举报原因:
原因补充:

(最多只允许输入30个字)