分治模板
meet in the middle:https://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\n",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\n",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\n",ans[i]); }