这题显然需要莫队,然后我就想着用非旋转 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;
}