「模板」數據結構

莫隊

#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$,單點查詢node

#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爆踩……我不知道我哪裏常數寫大了……ios

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;
相關文章
相關標籤/搜索