分治模板

meet in the middlehttps://www.lydsy.com/JudgeOnline/problem.php?id=4800

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1.1e6;
int n,len;
ll ans,m,n1,n2,c[50],a[N],b[N];
void dfs1(int u,ll s)
{
    if(s>m)return;
    if(u==len+1){a[++n1]=s;return;}
    dfs1(u+1,s),dfs1(u+1,s+c[u]);
}
void dfs2(int u,ll s)
{
    if(s>m)return;
    if(u==n+1){b[++n2]=s;return;}
    dfs2(u+1,s),dfs2(u+1,s+c[u]);
}
int main()
{
    scanf("%d%lld",&n,&m),len=n>>1;
    for(int i=1;i<=n;i++)scanf("%lld",&c[i]);
    dfs1(1,0),dfs2(len+1,0);
    sort(a+1,a+n1+1);
    sort(b+1,b+n2+1);
    for(int i=1,j=n2;i<=n1;i++)
    {
        while(a[i]+b[j]>m)j--;
        ans+=j;
    }
    printf("%lld",ans);
}

CDQ分治https://www.luogu.org/problemnew/show/P3810

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
struct node{int x,y,z,cnt,ans;}a[N];
int n,k,tot,C[N*2],num[N];
bool cmp(node a,node b)
{
    if(a.x==b.x)return a.y==b.y?a.z<b.z:a.y<b.y;
    return a.x<b.x;
}
bool dmp(node a,node b)
{
    if(a.y==b.y)return a.x==b.x?a.z<b.z:a.x<b.x;
    return a.y<b.y;
}
void update(int x,int v){while(x<=k)C[x]+=v,x+=x&-x;}
int query(int x){int ret=0;while(x)ret+=C[x],x-=x&-x;return ret;}
void cdq(int l,int r)
{
    if(l==r){a[l].ans+=a[l].cnt-1;return;}
    int mid=(l+r)/2;
    cdq(l,mid);cdq(mid+1,r);
    sort(a+l,a+mid+1,dmp),sort(a+mid+1,a+r+1,dmp);
    int j=l;
    for(int i=mid+1;i<=r;i++)
    {
        while(j<=mid&&a[j].y<=a[i].y)update(a[j].z,a[j].cnt),j++;
        a[i].ans+=query(a[i].z);
    }
    for(int i=l;i<j;i++)update(a[i].z,-a[i].cnt);
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
    sort(a+1,a+n+1,cmp);
    a[tot=1].cnt=1;
    for(int i=2;i<=n;i++)
    if(a[i].x==a[i-1].x&&a[i].y==a[i-1].y&&a[i].z==a[i-1].z)a[tot].cnt++;
    else a[++tot]=a[i],a[tot].cnt=1;
    cdq(1,tot);
    sort(a+1,a+tot+1,cmp);
    for(int i=1;i<=tot;i++)num[a[i].ans]+=a[i].cnt;
    for(int i=0;i<n;i++)printf("%d
",num[i]);
}

点分治https://www.lydsy.com/JudgeOnline/problem.php?id=1468

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=41000;
struct edge{int v,nxt,w;}e[N*2];
int n,k,sz[N],mx[N],head[N],d[N],a[N],top,cnt,root,ans;
bool vis[N];
void add(int u,int v,int w)
{e[++cnt]=(edge){v,head[u],w};head[u]=cnt;}
void dfs(int u,int fa)
{
    sz[u]=1;
    for(int i=head[u];i;i=e[i].nxt)
    if(e[i].v!=fa&&!vis[e[i].v])
    {
        dfs(e[i].v,u);
        sz[u]+=sz[e[i].v];
        mx[u]=max(mx[u],sz[e[i].v]);
    }
    mx[u]=max(mx[u],n-sz[u]);
    if(mx[u]<mx[root])root=u;
}
void getd(int u,int fa)
{
    a[++top]=d[u];
    for(int i=head[u];i;i=e[i].nxt)
    if(e[i].v!=fa&&!vis[e[i].v])
    {
        d[e[i].v]=d[u]+e[i].w;
        getd(e[i].v,u);
    }
}
int cal(int u,int x)
{
    d[u]=x;
    top=0;getd(u,0);
    sort(a+1,a+top+1);
    int ret=0,l=1,r=top;
    while(l<r)
    if(a[l]+a[r]<=k){ret+=r-l;l++;}else r--;
    return ret;
}
void solve(int u)
{
    ans+=cal(u,0);
    vis[u]=1;
    for(int i=head[u];i;i=e[i].nxt)
    if(!vis[e[i].v])
    {
        ans-=cal(e[i].v,e[i].w);
        root=0;
        dfs(e[i].v,0);
        solve(root);
    }
}
int main()
{
    scanf("%d",&n);
    mx[0]=n;
    int x,y,z;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);add(y,x,z);
    }
    scanf("%d",&k);
    dfs(1,0);
    solve(root);
    printf("%d",ans);
}

动态点分治https://www.luogu.org/problemnew/show/P3241

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=1.5e5+7,M=4e5+7;
struct node{int x,d;}p[N<<5];
int n,m,A,num,all,rt,tot,a[N],hd[N],v[M],nxt[M],w[M],sz[N],fa[N];
int L[N][3],R[N][3],cnt[N],son[N][3],in[N<<1],dfn[N<<1],dep[N],lg[N<<1],f[N<<1][18],sum[N];
ll ans,pre[N<<5];
bool vis[N];
void add(int x,int y,int z){v[++num]=y,w[num]=z,nxt[num]=hd[x],hd[x]=num;}
bool cmp(node x,node y){return a[x.x]<a[y.x];}
void getsz(int u,int fa)
{
    sz[u]=1;
    for(int i=hd[u];i;i=nxt[i])if(v[i]!=fa&&!vis[v[i]])getsz(v[i],u),sz[u]+=sz[v[i]];
}
void findroot(int u,int fa)
{
    int mx=0;
    for(int i=hd[u];i;i=nxt[i]) 
    if(v[i]!=fa&&!vis[v[i]])findroot(v[i],u),mx=max(mx,sz[v[i]]);
    mx=max(mx,all-sz[u]);
    if(mx<=all/2)rt=u;
}
void dfs(int u,int fa,int d)
{
    p[++tot]=(node){u,d};
    for(int i=hd[u];i;i=nxt[i])if(!vis[v[i]]&&v[i]!=fa)dfs(v[i],u,d+w[i]);
}
int solve(int u,int f)
{
    getsz(u,0),all=sz[u],findroot(u,0);
    int now=rt;
    for(int i=hd[now];i;i=nxt[i])
    if(!vis[v[i]])L[now][cnt[now]]=tot+1,dfs(v[i],now,w[i]),R[now][cnt[now]++]=tot;
    int ret=0;vis[now]=1,fa[now]=f;
    for(int i=hd[now];i;i=nxt[i])if(!vis[v[i]])son[now][ret++]=solve(v[i],now);
    return now;
}
void dfs2(int x,int fa)
{
    in[x]=++num,dfn[num]=x,dep[x]=dep[fa]+1;
    for(int i=hd[x];i;i=nxt[i])
    if(v[i]!=fa)sum[v[i]]=sum[x]+w[i],dfs2(v[i],x),dfn[++num]=x;
}
int lca(int x,int y)
{
    x=in[x],y=in[y];if(x>y)swap(x,y);
    int k=lg[y-x+1];
    return (dep[f[x][k]]<dep[f[y-(1<<k)+1][k]])?f[x][k]:f[y-(1<<k)+1][k];
}
int find(int l,int r,int v)
{
    int mid;r++;
    while(l<r)
    {
        mid=l+r>>1;
        (a[p[mid].x]<=v)?l=mid+1:r=mid;
    }
    return l-1;
}
ll query(int x,int v)
{
    ll ret=0;
    for(int lst=0,i=x;i;lst=i,i=fa[i])
    {
        int D=sum[x]+sum[i]-2*sum[lca(x,i)],pos;
        ret+=(a[i]<=v)*D;
        for(int j=0;j<cnt[i];j++)
        if(son[i][j]!=lst)
        pos=find(L[i][j],R[i][j],v),ret+=1ll*(pos-L[i][j]+1)*D+pre[pos]-pre[L[i][j]-1];
    }
    return ret;
}
int main()
{
    scanf("%d%d%d",&n,&m,&A);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1,x,y,z;i<n;i++)scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
    solve(1,0);
    for(int i=1;i<=n;i++)
    for(int j=0;j<cnt[i];j++)
    sort(p+L[i][j],p+R[i][j]+1,cmp);
    for(int i=1;i<=tot;i++)pre[i]=pre[i-1]+p[i].d;
    num=0,dfs2(1,0),lg[0]=-1;
    for(int i=1;i<=num;i++)f[i][0]=dfn[i],lg[i]=lg[i>>1]+1;
    for(int j=1;j<=17;j++)
    for(int i=1;i<=num-(1<<j);i++)
    f[i][j]=(dep[f[i][j-1]]<dep[f[i+(1<<j-1)][j-1]])?f[i][j-1]:f[i+(1<<j-1)][j-1];
    while(m--)
    {
        int x,l,r;scanf("%d%d%d",&x,&l,&r);
        l=(l+ans)%A,r=(r+ans)%A;
        if(l>r)swap(l,r);
        printf("%lld
",ans=query(x,r)-query(x,l-1));
    }
}

线段树分治https://www.luogu.org/problemnew/show/P4585

#include<bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int N=1e5+7;
struct guest{int l,r,L,R,x;}p[N];
struct buy{int s,v,t;}q[N],t1[N],t2[N];
int n,m,n1,n2,tot,top,rt[N],ans[N],st[N],ch[N*19][2],sz[N*19];
vector<int>a[N];
bool cmp(buy x,buy y){return x.s<y.s;}
void build(int&x,int u,int S)
{
    x=++tot;
    int now=x;
    for(int i=17;~i;i--)
    {
        bool d=S>>i&1;
        ch[now][d^1]=ch[u][d^1],ch[now][d]=++tot;
        now=ch[now][d],u=ch[u][d],sz[now]=sz[u]+1;
    }
}
int query(int l,int r,int S)
{
    int ret=0;
    for(int i=17;~i;i--)
    {
        bool d=S>>i&1;
        if(sz[ch[r][d^1]]-sz[ch[l][d^1]]>0)l=ch[l][d^1],r=ch[r][d^1],ret+=1<<i;
        else l=ch[l][d],r=ch[r][d];
    }
    return ret;
}
void update(int L,int R,int x,int l,int r,int rt)
{
    if(L>R)return;
    if(L<=l&&r<=R){a[rt].push_back(x);return;}
    int mid=l+r>>1;
    if(L<=mid)update(L,R,x,lson);
    if(R>mid)update(L,R,x,rson);
}
void calc(int x,int L,int R)
{
    top=tot=0;
    for(int i=L;i<=R;i++)st[++top]=q[i].s,build(rt[top],rt[top-1],q[i].v);
    for(int i=0,k,l,r;i<a[x].size();i++)
    {
        k=a[x][i];
        l=upper_bound(st+1,st+top+1,p[k].l-1)-st-1,r=upper_bound(st+1,st+1+top,p[k].r)-st-1;
        ans[k]=max(ans[k],query(rt[l],rt[r],p[k].x));
    }
}
void divide(int l,int r,int rt,int L,int R)
{
    if(L>R)return;
    int mid=l+r>>1,cnt1=0,cnt2=0;
    calc(rt,L,R);
    if(l==r)return;
    for(int i=L;i<=R;i++)if(q[i].t<=mid)t1[++cnt1]=q[i];else t2[++cnt2]=q[i];
    for(int i=1;i<=cnt1;i++)q[i+L-1]=t1[i];
    for(int i=1;i<=cnt2;i++)q[i+L-1+cnt1]=t2[i];
    divide(lson,L,L+cnt1-1);
    divide(rson,L+cnt1,R);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,x;i<=n;i++)scanf("%d",&x),build(rt[i],rt[i-1],x);
    for(int i=1,op,l,r,x,d;i<=m;i++)
    {
        scanf("%d%d%d",&op,&l,&r);
        if(!op)q[++n1]=(buy){l,r,n1};
        else{
            scanf("%d%d",&x,&d);
            ans[++n2]=query(rt[l-1],rt[r],x);
            p[n2]=(guest){l,r,max(1,n1-d+1),n1,x};
        }
    }
    for(int i=1;i<=n2;i++)update(p[i].L,p[i].R,i,1,n1,1);
    sort(q+1,q+n1+1,cmp);
    divide(1,n1,1,1,n1);
    for(int i=1;i<=n2;i++)printf("%d
",ans[i]);
}
原文地址:https://www.cnblogs.com/hfctf0210/p/11039159.html