【Codeforces633H】Fibonacci-ish II

這題顯然需要莫隊,然後我就想着用非旋轉treap 騙過去,然後光榮TLE了。(感覺我複雜度似乎也是錯的可能)

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define N 30009
#define rd(x) ((rand()*23333+rand())%(x))
using namespace std;
int n,mod,a[N],f[N],Q,lim,pos[N],Ans[N],now[N];
map<int,int> mp;
struct qry
{
    int l,r,id;
    bool operator <(const qry &rhs) const
    {
        return pos[l]<pos[rhs.l]||pos[l]==pos[rhs.l]&&r<rhs.r;
    }
}q[N];
struct Treap
{
   struct node
   {
       node *lson,*rson;
       int key,val,sum1,sum2,add,num,size;
       node(int x,int y)
       {
           add=0,num=y;
           sum2=(ll)x*f[y-1]%mod;
           val=x;
           sum1=(ll)x*f[y]%mod;
           key=rd(1000000000);
           lson=rson=NULL;
           size=1;
       }
   };
   typedef node * pnode;
   pnode root,L,R,rest;
   void init()
   {
       root=NULL;
   }
   void up(pnode now)
   {
       now->sum1=(ll)now->val%mod*f[now->num]%mod;
       if (now->lson) now->sum1+=now->lson->sum1;
       now->sum1%=mod;
       if (now->rson) now->sum1+=now->rson->sum1;
       now->sum1%=mod;
       now->sum2=(ll)now->val%mod*f[now->num-1]%mod;
       if (now->lson) now->sum2+=now->lson->sum2;
       now->sum2%=mod;
       if (now->rson) now->sum2+=now->rson->sum2;
       now->sum2%=mod;
       now->size=1;
       if (now->lson) now->size+=now->lson->size;
       if (now->rson) now->size+=now->rson->size;
   }
   void down(pnode now)
   {
       if (now->add>0)
       {
           if (now->lson)
           {
               now->lson->add+=now->add;
               now->lson->num+=now->add;
               int t1=now->lson->sum1,t2=now->lson->sum2;
               now->lson->sum1=((ll)f[now->add+1]*t1%mod+(ll)f[now->add]*t2%mod)%mod;
               now->lson->sum2=((ll)f[now->add]*t1%mod+(ll)f[now->add-1]*t2%mod)%mod;
           }
           if (now->rson)
           {
               now->rson->add+=now->add;
               now->rson->num+=now->add;
               int t1=now->rson->sum1,t2=now->rson->sum2;
               now->rson->sum1=((ll)f[now->add+1]*t1%mod+(ll)f[now->add]*t2%mod)%mod;
               now->rson->sum2=((ll)f[now->add]*t1%mod+(ll)f[now->add-1]*t2%mod)%mod;
           }
           now->add=0;
       }
       if (now->add<0)
       {
           if (now->lson)
           {
               now->lson->add+=now->add;
               now->lson->num+=now->add;
               int t1=now->lson->sum1,t2=now->lson->sum2;
               now->lson->sum1=((ll)f[-now->add-1]*t1%mod-(ll)f[-now->add]*t2%mod+mod)%mod;
               if ((-now->add)&1) now->lson->sum1=(mod-now->lson->sum1)%mod;
               now->lson->sum2=((ll)f[-now->add+1]*t2%mod-(ll)f[-now->add]*t1%mod+mod)%mod;
               if ((-now->add)&1) now->lson->sum2=(mod-now->lson->sum2)%mod;
           }
           if (now->rson)
           {
               now->rson->add+=now->add;
               now->rson->num+=now->add;
               int t1=now->rson->sum1,t2=now->rson->sum2;
               now->rson->sum1=((ll)f[-now->add-1]*t1%mod-(ll)f[-now->add]*t2%mod+mod)%mod;
               if ((-now->add)&1) now->rson->sum1=(mod-now->rson->sum1)%mod;
               now->rson->sum2=((ll)f[-now->add+1]*t2%mod-(ll)f[-now->add]*t1%mod+mod)%mod;
               if ((-now->add)&1) now->rson->sum2=(mod-now->rson->sum2)%mod;
           }
           now->add=0;
       }
   }
   pnode merge(pnode L,pnode R)
   {
       if (!L) return R;
       if (!R) return L;
       if (L->key>R->key)
       {
           down(L);
           L->rson=merge(L->rson,R);
           up(L);
           return L;
       }
       else
       {
           down(R);
           R->lson=merge(L,R->lson);
           up(R);
           return R;
       }
   }
   void split(pnode now,int val,pnode &L,pnode &R)
   {
       if (!now)
       {
           L=R=NULL;
           return;
       }
       down(now);
       if (val<=now->val)
       {
           split(now->lson,val,L,now->lson);
           R=now;
           up(R);
           return;
       }
       else
       {
           split(now->rson,val,now->rson,R);
           L=now;
           up(L);
           return;
       }
   }
   void ins(int x)
   {
       split(root,x,L,R);
       if (R)
       {
           R->add++;
           R->num++;
           int t=(R->sum1+R->sum2)%mod;
           R->sum2=R->sum1;
           R->sum1=t;
       }
       root=merge(L,new node(x,L?(L->size+1):1));
       root=merge(root,R);
   }
   void del(int x)
   {
       split(root,x,L,R);
       split(R,x+1,rest,R);
       if (R)
       {
           R->add--;
           R->num--;
           int t=(R->sum1-R->sum2+mod)%mod;
           R->sum1=R->sum2;
           R->sum2=t;
       }
       root=merge(L,R);
   }
}tr;
int read()
{
    int x=1;
    char ch;
    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
    int s=ch-'0';
    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';
    return s*x;
}
void Insert(int x)
{
    tr.ins(x);
}
void Delete(int x)
{
    tr.del(x);
}
void add(int x)
{
    if (!mp[x]) Insert(x);
    mp[x]++;
}
void del(int x)
{
    mp[x]--;
    if (!mp[x]) Delete(x);
}
int get_Ans()
{
    return tr.root->sum1;
}
int main()
{
    n=read(),mod=read();
    //n=30000,mod=30000;
    for (int i=1;i<=n;i++) a[i]=read();
        //a[i]=i;
    f[0]=0,f[1]=f[2]=1;
    for (int i=3;i<=n;i++) f[i]=(f[i-1]+f[i-2])%mod;
    Q=read();
    //Q=30000;
    for (int i=1;i<=Q;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;
        //q[i].l=rand()%n+1,q[i].r=q[i].l+(rand()%(n-q[i].l+1)),q[i].id=i;
    lim=(int)sqrt(n);
    for (int i=1;i<=n;i++) pos[i]=i/lim+1;
    sort(q+1,q+Q+1);
    tr.init();
    int l=1,r=0;
    for (int i=1;i<=Q;i++)
    {
        while (r<q[i].r) add(a[++r]);
        while (l>q[i].l) add(a[--l]);
        while (r>q[i].r) del(a[r--]);
        while (l<q[i].l) del(a[l++]);
        Ans[q[i].id]=get_Ans();
        //cout<<Ans[q[i].id]<<" "<<Get_Ans()<<endl;
    }
    for (int i=1;i<=Q;i++) printf("%d\n",Ans[i]);
    return 0;
}

然後聽說這道題可以線段樹,,然後聽說O(n2) 就可以過???
所以果斷水。

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define N 30009
#define rd(x) ((rand()*23333+rand())%(x))
using namespace std;
int n,mod,a[N],f[N],Q,lim,pos[N],Ans[N],now[N];
map<int,int> mp;
struct qry
{
    int l,r,id;
    bool operator <(const qry &rhs) const
    {
        return pos[l]<pos[rhs.l]||pos[l]==pos[rhs.l]&&r<rhs.r;
    }
}q[N];
struct Treap
{
   struct node
   {
       node *lson,*rson;
       int key,val,sum1,sum2,add,num,size;
       node(int x,int y)
       {
           add=0,num=y;
           sum2=(ll)x*f[y-1]%mod;
           val=x;
           sum1=(ll)x*f[y]%mod;
           key=rd(1000000000);
           lson=rson=NULL;
           size=1;
       }
   };
   typedef node * pnode;
   pnode root,L,R,rest;
   void init()
   {
       root=NULL;
   }
   void up(pnode now)
   {
       now->sum1=(ll)now->val%mod*f[now->num]%mod;
       if (now->lson) now->sum1+=now->lson->sum1;
       now->sum1%=mod;
       if (now->rson) now->sum1+=now->rson->sum1;
       now->sum1%=mod;
       now->sum2=(ll)now->val%mod*f[now->num-1]%mod;
       if (now->lson) now->sum2+=now->lson->sum2;
       now->sum2%=mod;
       if (now->rson) now->sum2+=now->rson->sum2;
       now->sum2%=mod;
       now->size=1;
       if (now->lson) now->size+=now->lson->size;
       if (now->rson) now->size+=now->rson->size;
   }
   void down(pnode now)
   {
       if (now->add>0)
       {
           if (now->lson)
           {
               now->lson->add+=now->add;
               now->lson->num+=now->add;
               int t1=now->lson->sum1,t2=now->lson->sum2;
               now->lson->sum1=((ll)f[now->add+1]*t1%mod+(ll)f[now->add]*t2%mod)%mod;
               now->lson->sum2=((ll)f[now->add]*t1%mod+(ll)f[now->add-1]*t2%mod)%mod;
           }
           if (now->rson)
           {
               now->rson->add+=now->add;
               now->rson->num+=now->add;
               int t1=now->rson->sum1,t2=now->rson->sum2;
               now->rson->sum1=((ll)f[now->add+1]*t1%mod+(ll)f[now->add]*t2%mod)%mod;
               now->rson->sum2=((ll)f[now->add]*t1%mod+(ll)f[now->add-1]*t2%mod)%mod;
           }
           now->add=0;
       }
       if (now->add<0)
       {
           if (now->lson)
           {
               now->lson->add+=now->add;
               now->lson->num+=now->add;
               int t1=now->lson->sum1,t2=now->lson->sum2;
               now->lson->sum1=((ll)f[-now->add-1]*t1%mod-(ll)f[-now->add]*t2%mod+mod)%mod;
               if ((-now->add)&1) now->lson->sum1=(mod-now->lson->sum1)%mod;
               now->lson->sum2=((ll)f[-now->add+1]*t2%mod-(ll)f[-now->add]*t1%mod+mod)%mod;
               if ((-now->add)&1) now->lson->sum2=(mod-now->lson->sum2)%mod;
           }
           if (now->rson)
           {
               now->rson->add+=now->add;
               now->rson->num+=now->add;
               int t1=now->rson->sum1,t2=now->rson->sum2;
               now->rson->sum1=((ll)f[-now->add-1]*t1%mod-(ll)f[-now->add]*t2%mod+mod)%mod;
               if ((-now->add)&1) now->rson->sum1=(mod-now->rson->sum1)%mod;
               now->rson->sum2=((ll)f[-now->add+1]*t2%mod-(ll)f[-now->add]*t1%mod+mod)%mod;
               if ((-now->add)&1) now->rson->sum2=(mod-now->rson->sum2)%mod;
           }
           now->add=0;
       }
   }
   pnode merge(pnode L,pnode R)
   {
       if (!L) return R;
       if (!R) return L;
       if (L->key>R->key)
       {
           down(L);
           L->rson=merge(L->rson,R);
           up(L);
           return L;
       }
       else
       {
           down(R);
           R->lson=merge(L,R->lson);
           up(R);
           return R;
       }
   }
   void split(pnode now,int val,pnode &L,pnode &R)
   {
       if (!now)
       {
           L=R=NULL;
           return;
       }
       down(now);
       if (val<=now->val)
       {
           split(now->lson,val,L,now->lson);
           R=now;
           up(R);
           return;
       }
       else
       {
           split(now->rson,val,now->rson,R);
           L=now;
           up(L);
           return;
       }
   }
   void ins(int x)
   {
       split(root,x,L,R);
       if (R)
       {
           R->add++;
           R->num++;
           int t=(R->sum1+R->sum2)%mod;
           R->sum2=R->sum1;
           R->sum1=t;
       }
       root=merge(L,new node(x,L?(L->size+1):1));
       root=merge(root,R);
   }
   void del(int x)
   {
       split(root,x,L,R);
       split(R,x+1,rest,R);
       if (R)
       {
           R->add--;
           R->num--;
           int t=(R->sum1-R->sum2+mod)%mod;
           R->sum1=R->sum2;
           R->sum2=t;
       }
       root=merge(L,R);
   }
}tr;
int read()
{
    int x=1;
    char ch;
    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
    int s=ch-'0';
    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';
    return s*x;
}
void Insert(int x)
{
    tr.ins(x);
}
void Delete(int x)
{
    tr.del(x);
}
void add(int x)
{
    if (!mp[x]) Insert(x);
    mp[x]++;
}
void del(int x)
{
    mp[x]--;
    if (!mp[x]) Delete(x);
}
int get_Ans()
{
    return tr.root->sum1;
}
int main()
{
    n=read(),mod=read();
    //n=30000,mod=30000;
    for (int i=1;i<=n;i++) a[i]=read();
        //a[i]=i;
    f[0]=0,f[1]=f[2]=1;
    for (int i=3;i<=n;i++) f[i]=(f[i-1]+f[i-2])%mod;
    Q=read();
    //Q=30000;
    for (int i=1;i<=Q;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;
        //q[i].l=rand()%n+1,q[i].r=q[i].l+(rand()%(n-q[i].l+1)),q[i].id=i;
    lim=(int)sqrt(n);
    for (int i=1;i<=n;i++) pos[i]=i/lim+1;
    sort(q+1,q+Q+1);
    tr.init();
    int l=1,r=0;
    for (int i=1;i<=Q;i++)
    {
        while (r<q[i].r) add(a[++r]);
        while (l>q[i].l) add(a[--l]);
        while (r>q[i].r) del(a[r--]);
        while (l<q[i].l) del(a[l++]);
        Ans[q[i].id]=get_Ans();
        //cout<<Ans[q[i].id]<<" "<<Get_Ans()<<endl;
    }
    for (int i=1;i<=Q;i++) printf("%d\n",Ans[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章