2019.03.29 bzoj3323: [Scoi2013]多项式的运算(非旋treap)

传送门

题意:定义一个无穷项的多项式f(x)f(x)f(x),初始各项系数都为0,现在有几种操作

  1. 将xLx^LxL到xRx^RxR这些项的系数乘上某个定值v

  2. 将xLx^LxL到xRx^RxR这些项的系数加上某个定值v

  3. 将xLx^LxL到xRx^RxR这些项乘上x变量

  4. 将某个定值v代入多项式F(x),并输出代入后多项式的值,之后多项式还原为代入前的状况

其中第四种操作不会出现超过10次。

N≤105,0≤L≤R≤105,0≤v≤109N\le10^5,0\le L\le R \le10^5,0 \le v\le10^9N≤105,0≤L≤R≤105,0≤v≤109


思路:

由于第四个操作不会出现超过101010次因此如果能快速维护各项系数可以O(n)O(n)O(n)遍历。

头两个操作是基操我们跳过吧qwqqwqqwq

主要看第三个操作,想象我们对x0x^0x0~x100001x^{100001}x100001这些项的系数用一棵平衡树来维护,这样操作三相当于将xrx^rxr的系数加到xr+1x^{r+1}xr+1上面,然后删掉这个xrx^rxr,然后把xlx^lxl ~xr−1x^{r-1}xr−1对应次数全部加111,然后插入一个新的系数为000的xlx^lxl。

于是这道题就做完了。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
    #define gc getchar
    int ans=0;
    char ch=gc();
    while(!isdigit(ch))ch=gc();
    while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
    return ans;
    #undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int N=2e5+5,mod=20130426;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
int pw[N],ans,n=100001;
namespace bst{
    #define lc (son[p][0])
    #define rc (son[p][1])
    int val[N],coe[N],siz[N],det[N],ad[N],ml[N],son[N][2],rd[N],rt=0,tot=0;
    inline int get(int v){return val[++tot]=v,siz[tot]=ml[tot]=1,rd[tot]=rand(),tot;}
    inline void pushup(int p){siz[p]=siz[lc]+1+siz[rc];}
    inline void pushval(int p,int v){if(!p)return;val[p]+=v,det[p]+=v;}
    inline void pushnow(int p,int v1,int v2){if(!p)return;coe[p]=add(mul(coe[p],v1),v2),ad[p]=add(mul(ad[p],v1),v2),ml[p]=mul(ml[p],v1);}
    inline void pushdown(int p){
        if(det[p]){
            if(lc)pushval(lc,det[p]);
            if(rc)pushval(rc,det[p]);
            det[p]=0;
        }
        if(ad[p]||ml[p]!=1){
            if(lc)pushnow(lc,ml[p],ad[p]);
            if(rc)pushnow(rc,ml[p],ad[p]);
            ml[p]=1,ad[p]=0;
        }
    }
    inline int merge(int a,int b){
        if(!a||!b)return a+b;
        pushdown(a),pushdown(b);
        if(rd[a]>rd[b])return son[a][1]=merge(son[a][1],b),pushup(a),a;
        return son[b][0]=merge(a,son[b][0]),pushup(b),b;
    }
    inline pii split(int p,int k){
        if(!p)return pii(0,0);
        pii tmp;
        pushdown(p);
        if(siz[lc]>=k)return tmp=split(lc,k),lc=tmp.se,pushup(p),pii(tmp.fi,p);
        return tmp=split(rc,k-siz[lc]-1),rc=tmp.fi,pushup(p),pii(p,tmp.se);
    }
    inline void insert(int id,int v){
        pii x=split(rt,id-1);
        rt=merge(x.fi,merge(get(v),x.se));
    }
    inline void build(int&p,int l,int r){
        if(l>r)return;
        int mid=l+r>>1;
        if(l==r){p=get(l-1);return;}
        p=get(mid-1),build(lc,l,mid-1),build(rc,mid+1,r),pushup(p);
    }
    inline void update(int l,int r,int v1,int v2){
        pii x=split(rt,l-1),y=split(x.se,r-l+1);
        pushnow(y.fi,v1,v2),rt=merge(x.fi,merge(y.fi,y.se));
    }
    inline void modify(int l,int r){
        pii x=split(rt,l-1),y=split(x.se,r-l+2),z=split(y.fi,r-l),t=split(z.se,1);
        coe[t.se]=add(coe[t.se],coe[t.fi]),pushval(z.fi,1),rt=merge(x.fi,merge(merge(z.fi,t.se),y.se));
        insert(l,l-1);
    }
    inline void query(int p){
        ans=add(ans,mul(pw[val[p]],coe[p]));
        pushdown(p);
        if(lc)query(lc);
        if(rc)query(rc);
    }
    #undef lc
    #undef rc
}
char s[5];
int main(){
    srand(time(NULL));
    bst::build(bst::rt,1,n+1);
    for(ri tt=read(),l,r,v;tt;--tt){
        scanf("%s",s);
        if(s[0]=='a'){
            l=read()+1,r=read()+1,v=read()%mod;
            bst::update(l,r,1,v);
        }
        if(s[0]=='m'&&strlen(s)==3){
            l=read()+1,r=read()+1,v=read()%mod;
            bst::update(l,r,v,0);
        }
        if(s[0]=='m'&&strlen(s)==4){
            l=read()+1,r=read()+1;
            bst::modify(l,r);
        }
        if(s[0]=='q'){
            v=read();
            pw[0]=1;
            ans=0;
            for(ri i=1;i<=n;++i)pw[i]=mul(pw[i-1],v);
            bst::query(bst::rt);
            cout<<ans<<'\n';
        }
    }
    return 0;
}
上一篇:es6简单介绍


下一篇:Django-分页、中间件和请求的声明周期