#include<iostream>
#include<cstdio>
#include<cstring>
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
using namespace std;
long long node[400001],a[100001];
int n,p,m;
long long delta[400001][2],ans;
void updata(int i)
{
node[i]=(node[i<<1]+node[i<<1|1])%p;
}
void build(int i,int l,int r)
{
delta[i][0]=1;
delta[i][1]=0;
if (l==r)
{
node[i]=a[l]%p;
return;
}
build(lch); build(rch);
updata(i);
}
void paint(int i,int l,int r,long long k,long long a)
{
int t;
a=a%p; k=k%p; t=(r-l+1)%p;
node[i]=((node[i]*k)%p+(a*t)%p)%p;
delta[i][0]=(delta[i][0]*k)%p;
delta[i][1]=((delta[i][1]*k)%p+a)%p;
}
void pushdown(int i,int l,int r)
{
paint(lch,delta[i][0],delta[i][1]);
paint(rch,delta[i][0],delta[i][1]);
delta[i][0]=1; delta[i][1]=0;
}
void insert(int i,int l,int r,int x,int y,long long a,int kind)
{
if (x<=l&&y>=r)
{
if (kind==2)
paint(i,l,r,1,a);
if (kind==1)
paint(i,l,r,a,0);
return;
}
pushdown(i,l,r);
if (x<=mid) insert(lch,x,y,a,kind);
if (y>mid) insert(rch,x,y,a,kind);
updata(i);
}
void query(int i,int l,int r,int x,int y)
{
if (x<=l&&y>=r)
{
ans=(node[i]+ans)%p;
return;
}
pushdown(i,l,r);
if (x<=mid) query(lch,x,y);
if (y>mid) query(rch,x,y);
}
int main()
{
freopen("seqb.in","r",stdin);
freopen("seqb.out","w",stdout);
int i,kind,t,g,c;
scanf("%d%d",&n,&p);
for (i=1;i<=n;++i)
scanf("%d",&a[i]);
build(1,1,n);
scanf("%d",&m);
for (i=1;i<=m;++i)
{
scanf("%d",&kind);
if (kind==1||kind==2)
{
c=c%p;
scanf("%d%d%d",&t,&g,&c);
insert(1,1,n,t,g,c,kind);
}
if (kind==3)
{
scanf("%d%d",&t,&g);
ans=0; query(1,1,n,t,g);
printf("%lld\n",ans);
}
}
fclose(stdin);
fclose(stdout);
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COGS 三元数对&&数列
统计在某数之前比某数小和某数之后比某数小(或大)的个数,思路很奇特,以数字为节点建树,然后在线单点修改,区间求值。。。
三元数对(离散化)code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
using namespace std;
int node[200000],n;
int a[30001],b[30001];
int minn[30001];
int ans;
long long sum;
void updata(int i)
{
node[i]=node[i<<1]+node[i<<1|1];
}
void insert(int i,int l,int r,int x)
{
if (l==r&&l==x)
{
node[i]+=1;
return;
}
if (x<=mid) insert(lch,x);
else insert(rch,x);
updata(i);
}
void query(int i,int l,int r,int x,int y)
{
if (x<=l&&y>=r)
{
ans+=node[i];
return;
}
if (x<=mid) query(lch,x,y);
if (y>mid) query(rch,x,y);
}
int main()
{
int i,size;
freopen("three.in","r",stdin);
freopen("three.out","w",stdout);
scanf("%d",&n);
sum=0;
for (i=1;i<=n;++i)
{
scanf("%d",&a[i]);
a[i]+=2;
b[i]=a[i];
}
sort(b+1,b+n+1);
size=unique(b+1,b+n+1)-b-1;
for (i=1;i<=n;++i)
a[i]=upper_bound(b+1,b+size+1,a[i])-b;
size++;
memset(node,0,sizeof(node));
for (i=1;i<=n;++i)
{
insert(1,1,size,a[i]);
if (i>1)
{
ans=0;
query(1,1,size,1,a[i]-1);
minn[i]=ans;
}
}
memset(node,0,sizeof(node));
for (i=n;i>=1;--i)
{
insert(1,1,size,a[i]);
if (i<n)
{
ans=0;
query(1,1,size,a[i]+1,size);
if (i>1)
sum+=ans*minn[i];
}
}
printf("%lld\n",sum);
fclose(stdin);
fclose(stdout);
}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TYVJ 1728 普通平衡树
一道著名的平衡树练习题,我们考虑它的线段树做法(做死了。。。),首先离散化(为了输出原数搞一个类似映射的东西),然后以数为节点建立线段树,然后blabla乱搞就好了(蒟蒻的算法常数很大,很大) code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
using namespace std;
int node[400001],n;
struct hp{
int kind,x;
}opt[100001];
int b[100001];
int f[100001],ans,rank,ansi;
void updata(int i)
{
node[i]=node[i<<1]+node[i<<1|1];
}
void insert(int i,int l,int r,int x,int a)
{
if (l==r&&l==x)
{
node[i]+=a;
return;
}
if (x<=mid) insert(lch,x,a);
else insert(rch,x,a);
updata(i);
}
void querynum(int i,int l,int r,int x)
{
if (l==r&&l==x)
{ansi=i; ans++; return;}
if (x<=mid)
querynum(lch,x);
else
{
ans+=node[i<<1];
querynum(rch,x);
}
}
void queryx(int i,int l,int r,int x)
{
if (l==r&&rank<=x&&rank+node[i]>=x)
{
ans=l;
return;
}
if (rank+node[i<<1]>=x)
queryx(lch,x);
else
{
rank+=node[i<<1];
queryx(rch,x);
}
}
int main()
{
int t,i,size;
freopen("phs.in","r",stdin);
freopen("phs.out","w",stdout);
scanf("%d",&n);
for (i=1;i<=n;++i)
{
scanf("%d%d",&opt[i].kind,&opt[i].x);
b[i]=opt[i].x;
}
sort(b+1,b+n+1);
size=unique(b+1,b+n+1)-b-1;
for (i=1;i<=n;++i)
{
t=lower_bound(b+1,b+size+1,opt[i].x)-b;
f[t]=opt[i].x;
opt[i].x=t;
}
for (i=1;i<=n;++i)
{
if (opt[i].kind==1)
insert(1,1,size,opt[i].x,1);
if (opt[i].kind==2)
insert(1,1,size,opt[i].x,-1);
if (opt[i].kind==3)
{
ans=0;
querynum(1,1,size,opt[i].x);
printf("%d\n",ans);
}
if (opt[i].kind==4)
{
rank=0;
queryx(1,1,size,f[opt[i].x]);
printf("%d\n",f[ans]);
}
if (opt[i].kind==5)
{
ans=0;
querynum(1,1,size,opt[i].x);
rank=0;
queryx(1,1,size,ans-1);
printf("%d\n",f[ans]);
}
if (opt[i].kind==6)
{
ans=0;
querynum(1,1,size,opt[i].x);
rank=0;
queryx(1,1,size,ans+node[ansi]);
printf("%d\n",f[ans]);
}
}
fclose(stdin);
fclose(stdout);
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Lcomyn