「模板」数据结构
莫队
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=50005;
int n,m,k;
int cnt[N],a[N],size,p,ans[N];
struct query
{
int l,r,id,bel;
}q[N];
int cmp(query x,query y)
{
return x.bel!=y.bel?x.l<y.l:((x.bel&1)?x.r<y.r:x.r>y.r);
}
int read()
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x;
}
int main()
{
n=read();m=read();k=read();
size=(int)sqrt(n);
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=m;i++)
q[i].l=read(),q[i].r=read(),q[i].id=i,q[i].bel=(q[i].l-1)/size+1;
sort(q+1,q+m+1,cmp);
/*for(int i=1;i<=m;i++)
cout<<q[i].id<<' '<<q[i].l<<' '<<q[i].r<<' '<<endl;*/
int l=1,r=0;
for(int i=1;i<=m;i++)
{
int ql=q[i].l,qr=q[i].r;
while(l<ql)cnt[a[l]]--,p-=2*cnt[a[l]]+1,l++;
while(l>ql)l--,cnt[a[l]]++,p+=2*cnt[a[l]]-1;
while(r<qr)r++,cnt[a[r]]++,p+=2*cnt[a[r]]-1;
while(r>qr)cnt[a[r]]--,p-=2*cnt[a[r]]+1,r--;
ans[q[i].id]=p;
}
for(int i=1;i<=m;i++)
cout<<ans[i]<<endl;
return 0;
}
ST表
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100005;
int n,m;
int st[N][20],a[N];
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
int lg[N]={-1};
void ini()
{
for(int i=1;i<=n;i++)
st[i][0]=a[i],lg[i]=lg[i>>1]+1;
for(int i=1;i<=lg[n];i++)
for(int j=1;j+(1<<i)-1<=n;j++)
st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
int query(int l,int r)
{
int len=lg[r-l+1];
return max(st[l][len],st[r-(1<<len)+1][len]);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
a[i]=read();
ini();
while(m--)
{
int l=read(),r=read();
printf("%d\n",query(l,r));
}
return 0;
}
主席树
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100005;
int type,n,m,side;
int sum[N*20],root[N*20],ls[N*20],rs[N*20];
int a[N],b[N];
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9')
{if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')
{x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void build(int &k,int l,int r)
{
k=++type;
sum[k]=0;
if(l==r)return ;
int mid=l+r>>1;
build(ls[k],l,mid);
build(rs[k],mid+1,r);
}
void update(int &k,int l,int r,int time,int val)
{
k=++type;
ls[k]=ls[time];
rs[k]=rs[time];
sum[k]=sum[time]+1;
if(l==r)return ;
int mid=l+r>>1;
if(val<=mid)update(ls[k],l,mid,ls[time],val);
else update(rs[k],mid+1,r,rs[time],val);
}
int query(int k1,int k2,int l,int r,int val)
{
if(l==r)return l;
int mid=l+r>>1;
int cnt=sum[ls[k2]]-sum[ls[k1]];
if(val<=cnt)return query(ls[k1],ls[k2],l,mid,val);
else return query(rs[k1],rs[k2],mid+1,r,val-cnt);
}
void work()
{
int l=read(),r=read(),val=read();
int ans=query(root[l-1],root[r],1,side,val);
printf("%d\n",b[ans]);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)a[i]=read(),b[i]=a[i];
sort(b+1,b+n+1);
side=unique(b+1,b+n+1)-b-1;
build(root[0],1,side);
for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+side+1,a[i])-b;
for(int i=1;i<=n;i++)update(root[i],1,side,root[i-1],a[i]);
while(m--)work();
return 0;
}
主席树求区间前驱后继:
int askpre(int k1,int k2,int l,int r,int val)
{
if(sum[k2]-sum[k1]==0)return -1;
if(l==r)return l;
int mid=l+r>>1;
if(mid<val)
{
int ret=askpre(rs[k1],rs[k2],mid+1,r,val);
if(ret==-1)ret=askpre(ls[k1],ls[k2],l,mid,val);
return ret;
}
else return askpre(ls[k1],ls[k2],l,mid,val);
}
int asknxt(int k1,int k2,int l,int r,int val)
{
if(sum[k2]-sum[k1]==0)return -1;
if(l==r)return l;
int mid=l+r>>1;
if(mid>=val)
{
int ret=asknxt(ls[k1],ls[k2],l,mid,val);
if(ret==-1)ret=asknxt(rs[k1],rs[k2],mid+1,r,val);
return ret;
}
else return asknxt(rs[k1],rs[k2],mid+1,r,val);
}
树剖
#include<cstdio>
#include<iostream>
#include<cstring>
#define up sum[k]=(sum[ls(k)]+sum[rs(k)])%mod
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=1e5+5;
int n,m,root,mod;
int w[N],to[N<<1],head[N],nxt[N<<1],tot;
int dep[N],size[N],fa[N],son[N],id[N],type,rew[N];
int top[N];
int sum[N<<2],lz[N<<2];
void dfs1(int x,int f)
{
dep[x]=dep[f]+1;
fa[x]=f;size[x]=1;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f)continue;
dfs1(y,x);
size[x]+=size[y];
if(size[y]>size[son[x]])son[x]=y;
}
}
void dfs2(int x,int topf)
{
id[x]=++type;
rew[id[x]]=w[x];
top[x]=topf;
if(!son[x])return ;
dfs2(son[x],topf);
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(top[y])continue;
dfs2(y,y);
}
}
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
#define ls(k) (k)<<1
#define rs(k) (k)<<1|1
void build(int k,int l,int r)
{
if(l==r)
{
sum[k]=rew[l]%mod;
return ;
}
int mid=l+r>>1;
build(ls(k),l,mid);
build(rs(k),mid+1,r);
up;
}
void down(int k,int l,int r)
{
if(!lz[k])return ;
int mid=l+r>>1;
(lz[ls(k)]+=lz[k])%=mod;
(lz[rs(k)]+=lz[k])%=mod;
(sum[ls(k)]+=1LL*(mid-l+1)*lz[k])%=mod;
(sum[rs(k)]+=1LL*(r-mid)*lz[k])%=mod;
lz[k]=0;
return ;
}
void change(int k,int l,int r,int L,int R,int val)
{
if(L<=l&&R>=r)
{
(sum[k]+=1LL*(r-l+1)*val%mod)%=mod;
(lz[k]+=val)%=mod;
return ;
}
down(k,l,r);
int mid=l+r>>1;
if(L<=mid)change(ls(k),l,mid,L,R,val);
if(R>mid)change(rs(k),mid+1,r,L,R,val);
up;
}
int query(int k,int l,int r,int L,int R)
{
if(L<=l&&R>=r)return sum[k];
int mid=l+r>>1,res=0;
down(k,l,r);
if(L<=mid)(res+=query(ls(k),l,mid,L,R))%=mod;
if(R>mid)(res+=query(rs(k),mid+1,r,L,R))%=mod;
return res;
}
int ask(int x,int y)
{
int res=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
(res+=query(1,1,n,id[top[x]],id[x]))%=mod;
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
(res+=query(1,1,n,id[x],id[y]))%=mod;
return res;
}
void update(int x,int y,int val)
{
val%=mod;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
change(1,1,n,id[top[x]],id[x],val);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
change(1,1,n,id[x],id[y],val);
}
int askson(int x){return query(1,1,n,id[x],id[x]+size[x]-1);}
void upson(int x,int val){change(1,1,n,id[x],id[x]+size[x]-1,val);return ;}
int main()
{
/*freopen("testdata.in","r",stdin);
freopen("my.out","w",stdout);*/
n=read();m=read();
root=read();mod=read();
for(int i=1;i<=n;i++)
w[i]=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
dfs1(root,0);dfs2(root,root);
build(1,1,n);
while(m--)
{
int op=read(),x,y,z;
switch(op)
{
case 1:x=read();y=read();z=read();update(x,y,z);break;
case 2:x=read();y=read();printf("%d\n",ask(x,y));break;
case 3:x=read();z=read();upson(x,z);break;
case 4:x=read();printf("%d\n",askson(x));break;
}
}
return 0;
}
二维线段树
矩阵取$max$,单点查询
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int base=1001,M=2002,inf=0x3f3f3f3f;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int maxx=-inf,minx=inf,maxy=-inf,miny=inf,ans;
int n;
struct node
{
node *ls,*rs;
node *ys;
int v;
node()
{
ls=rs=NULL;
v=0;
}
};
node *root;
void judge(node *&k)
{
if(k==NULL)k=new node();
}
void upy(node *&k,int l,int r,int x,int y,int xx,int yy,int val)
{
if(y<=l&&yy>=r)
{
k->v=max(val,k->v);return ;
}
int mid=l+r>>1;
if(y<=mid)
{
judge(k->ls);
upy(k->ls,l,mid,x,y,xx,yy,val);
}
if(yy>mid)
{
judge(k->rs);
upy(k->rs,mid+1,r,x,y,xx,yy,val);
}
}
void upx(node *&k,int l,int r,int x,int y,int xx,int yy,int val)
{
if(x<=l&&xx>=r)
{
judge(k->ys);
upy(k->ys,1,M,x,y,xx,yy,val);
return ;
}
int mid=l+r>>1;
if(x<=mid)
{
judge(k->ls);
upx(k->ls,l,mid,x,y,xx,yy,val);
}
if(xx>mid)
{
judge(k->rs);
upx(k->rs,mid+1,r,x,y,xx,yy,val);
}
}
void asky(node *&k,int l,int r,int x,int y)
{
ans=max(ans,k->v);
if(l==r)return ;
int mid=l+r>>1;
if(y<=mid)
{
judge(k->ls);
asky(k->ls,l,mid,x,y);
}
else
{
judge(k->rs);
asky(k->rs,mid+1,r,x,y);
}
}
void askx(node *&k,int l,int r,int x,int y)
{
judge(k->ys);
asky(k->ys,1,M,x,y);
if(l==r)return ;
int mid=l+r>>1;
if(x<=mid)judge(k->ls),askx(k->ls,l,mid,x,y);
else judge(k->rs),askx(k->rs,mid+1,r,x,y);
}
int vis[100005];
#define F
int main()
{
#ifdef F
freopen("excel.in","r",stdin);
freopen("excel.out","w",stdout);
#endif
n=read();root=new node();
for(int q=1;q<=n;q++)
{
int x=read()+base+1,y=read()+base+1,xx=read()+base,yy=read()+base;
swap(x,y);swap(xx,yy);
minx=min(minx,x);maxx=max(maxx,xx);
miny=min(miny,y);maxy=max(maxy,yy);
upx(root,1,M,x,y,xx,yy,q);
}
int cnt=1;
for(int i=minx;i<=maxx;i++)
{
for(int j=miny;j<=maxy;j++)
{
ans=0;askx(root,1,M,i,j);
if(ans&&!vis[ans])vis[ans]=1,cnt++;
}
}
printf("%d\n",cnt);
return 0;
}
配对堆
跑蚯蚓的暴力被STL爆踩……我不知道我哪里常数写大了……
struct stack
{
int s[M];
int tp,cnt;
inline int top()
{
if(!tp)return ++cnt;
return s[tp--];
}
inline void push(int x){s[++tp]=x;}
}node,edge;
struct Pairheap
{
int root,fa[M],val[M];
int sz;
int head[M],to[M],nxt[M],que[M];
inline void add(int x,int y)
{
int tot=edge.top();
to[tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
inline int merge(int x,int y)
{
if(val[x]<val[y])swap(x,y);
add(x,y);fa[y]=x;
return x;
}
inline void push(int Val)
{
++sz;
int x=node.top();
val[x]=Val;
root=root?merge(root,x):x;
}
inline int top()
{
return val[root];
}
inline void pop()
{
--sz;
re int l=0,r=0;
for(re int i=head[root];i;i=nxt[i])
{
int y=to[i];
edge.push(i);
if(fa[y]==root)fa[y]=0,que[++r]=y;
}
node.push(root);
head[root]=fa[root]=0;
val[root]=0;root=0;
while(l<r)
{
++l;if(l==r){root=que[l];return ;}
int x=que[l],y=que[++l];
que[++r]=merge(x,y);
}
}
inline int size(){return sz;}
}q;
兴许青竹早凋,碧梧已僵,人事本难防。

浙公网安备 33010602011771号