BZOJ3323: [Scoi2013]多项式的运算

题解: 直接splay就好了 这题最大的亮点是 区间平移 我们可以通过把r和r+1节点合并 然后在l-1加上一个节点实现

#include <bits/stdc++.h>
const int MAXN=3e5+10;
const int inf=2e5+2;
#define ll long long
using namespace std;
const int mod=20130426;
int ch[MAXN][2],size[MAXN],pre[MAXN],rt,cnt;
ll tag1[MAXN],tag2[MAXN],key[MAXN];//tag1 jia tag2 cheng
void newnode(int &x,int y){
    x=++cnt;ch[x][0]=ch[x][1]=0;key[x]=0;size[x]=1;pre[x]=y;
    tag1[x]=0;tag2[x]=1;
}
void add(int r,int vul){
    if(!r)return ;
    vul%=mod;
    tag1[r]+=vul;key[r]+=vul;
    tag1[r]%=mod;key[r]%=mod;
}
void mul(int r,ll vul){
    if(!r)return ;
    vul%=mod;
    tag2[r]*=1LL*vul;tag2[r]%=mod;
    tag1[r]*=1LL*vul;tag1[r]%=mod;
    key[r]*=1LL*vul;key[r]%=mod;
}
void push(int x){
    if(tag2[x]!=1){
        mul(ch[x][0],tag2[x]);
        mul(ch[x][1],tag2[x]);
        tag2[x]=1;
    }
    if(tag1[x]!=0){
        add(ch[x][0],tag1[x]);
        add(ch[x][1],tag1[x]);
        tag1[x]=0;
    }
}
void up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}
void P(int x){
    if(pre[x])P(pre[x]);
    push(x);
}
void rotate(int x,int kind){
    int y=pre[x];
    ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y;
    if(pre[y])ch[pre[y]][ch[pre[y]][1]==y]=x;
    pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
    up(y);
}
void splay(int x,int goal){
    P(x);
    while(pre[x]!=goal){
        if(pre[pre[x]]==goal)rotate(x,ch[pre[x]][0]==x);
        else{
            int y=pre[x];int kind=ch[pre[y]][0]==y;
            if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
            else rotate(y,kind),rotate(x,kind);
        }
    }
    if(goal==0)rt=x;
    up(x);
}
int find1(int x,int sz){
    push(rt);
    if(sz==size[ch[x][0]]+1)return x;
    else if(sz<=size[ch[x][0]])return find1(ch[x][0],sz);
    else return find1(ch[x][1],sz-size[ch[x][0]]-1);
    up(rt);
}
void Add(){
    int l,r,v;scanf("%d%d%d",&l,&r,&v);
    splay(find1(rt,l+1),0);splay(find1(rt,r+3),rt);
    add(ch[ch[rt][1]][0],v);
}
void Mul(){
    int l,r;ll v;scanf("%d%d%lld",&l,&r,&v);
    splay(find1(rt,l+1),0);splay(find1(rt,r+3),rt);
    mul(ch[ch[rt][1]][0],v);
}
void update(){
    int l,r;scanf("%d%d",&l,&r);
    splay(find1(rt,r+1),0);splay(find1(rt,r+3),rt);
    int t=ch[ch[rt][1]][0];ch[ch[rt][1]][0]=0;up(ch[rt][1]);up(rt);
    pre[t]=0;splay(find1(rt,r+2),0);key[rt]+=key[t];key[rt]%=mod;
    size[t]=1;tag1[t]=0;tag2[t]=1;key[t]=0;ch[t][0]=ch[t][1]=0;
    splay(find1(rt,l+1),0);splay(find1(rt,l+2),rt);
    ch[ch[rt][1]][0]=t;pre[t]=ch[rt][1];up(ch[rt][1]);up(rt);
}
int st[MAXN],tot;
void dfs(int x){
    if(!x)return ;
    push(x);
    dfs(ch[x][0]);
    st[++tot]=key[x];
    dfs(ch[x][1]);
    up(x);
}
void querty(){
    ll v;scanf("%lld",&v);
    tot=0;ll ans=0;ll x=1;
    dfs(rt);
    for(int i=2;i<=tot;i++)ans=(ans+1LL*st[i]*x)%mod,x=x*v%mod;
    printf("%lld\n",ans);
}
void built(int &x,int l,int r,int y){
    if(l>r)return ;
    int mid=(l+r)>>1;
    newnode(x,y);
    built(ch[x][0],l,mid-1,x);
    built(ch[x][1],mid+1,r,x);
    up(x);
}
void inte(){
    newnode(rt,0);newnode(ch[rt][1],rt);
    built(ch[ch[rt][1]][0],1,inf,ch[rt][1]);
    up(ch[rt][1]);up(rt);
}
char str[11];
int main(){
    inte();
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",str);
        if(str[0]=='a')Add();
        else if(str[0]=='q')querty();
        else{
            int len=strlen(str);
            if(len==4)update();
            else Mul();
        }
    }
    return 0;
}

 

3323: [Scoi2013]多项式的运算

Time Limit: 20 Sec  Memory Limit: 64 MB
Submit: 456  Solved: 166
[Submit][Status][Discuss]

Description

某天,mzry1992 一边思考着一个项目问题一边在高速公路上骑着摩托车。一个光头踢了他一脚,摩托车损坏,而他也被送进校医院打吊针。现在该项目的截止日期将近,他不得不请你来帮助他完成这个项目。该项目的目的是维护一个动态的关于x 的无穷多项式F(x) = a0 * x^0 + a1 * x^1 + a2 * x^2 + ... ,这个多项式初始时对于所有i有ai = 0。
操作者可以进行四种操作:
1. 将x^L 到x^R 这些项的系数乘上某个定值v
2. 将x^L 到x^R 这些项的系数加上某个定值v
 
3. 将x^L 到x^R 这些项乘上x变量
4. 将某个定值v代入多项式F(x),并输出代入后多项式的值,之后多项式还原为代入前的状况
经过观察,项目组发现使用者的操作集中在前三种,第四种操作不会出现超过10次。mzry1992 负责这个项目的核心代码,你能帮他实现么。

Input

输入的第一行有一个整数n 代表操作的个数。
接下来n 行,每行一个操作,格式如下:
mul L R v 代表第一种操作
add L R v 代表第二种操作
mulx L R 代表第三种操作
query v 代表第四种操作

对于30% 的数据:N <= 5000,0 <= L <= R <= 5000,0 <= v <= 10^9
另有20% 的数据:N <= 10^5,0 <= L <= R <= 10^5,0 <= v <= 10^9,没有mulx 操作
剩下的50% 的数据:N <= 10^5,0 <= L <= R <= 10^5,0 <= v <= 10^9

Output

对于每个query 操作,输出对应的答案,结果可能较大,需要模上20130426。

Sample Input

6
add 0 1 7
query 1
mul 0 1 7
query 2
mulx 0 1
query 3

Sample Output

14
147
588
Hint
操作一之后,多项式为F(x) = 7x + 7。
操作三之后,多项式为F(x) = 49x + 49。
操作五之后,多项式为F(x) = 49x^2 + 49x。

HINT

应上传者要求,此系列试题不公开,如有异议,本站将删除之。

posted @ 2018-08-17 12:23  wang9897  阅读(168)  评论(0编辑  收藏  举报