重修 CDQ 分治
简介
把动态问题转化为静态问题。
静态问题:没有修改操作的问题,或者所有查询操作都在修改操作之后的问题
动态问题:修改和查询操作交叉的问题
例题
P3810 【模板】三维偏序(陌上花开)
就是个模板。
P4390 [BOI2007]Mokia 摩基亚
我们按照时间分治 :
-
先 ,因为时间无后效性。
-
再计算 的加点操作给 的贡献。
-
最后,由于 对 的贡献已经算完,直接放心 。
所以这层分治之内唯一要解决的就是第二步。
求矩形和可以二维差分转化为四个 2-sides 矩形。
所以这道题可转化为静态问题:
给定平面上的一些点(带点权)和一些询问,每次询问需回答在一个坐标左下角的点权和。
这可以类似扫描线解决。
点击查看代码
//We'll be counting stars. //#pragma GCC optimize("Ofast") #include<bits/stdc++.h> using namespace std; #define IOS ios::sync_with_stdio(false) #define fir first #define sec second #define mkp make_pair #define pb emplace_back #define mem(x,y) memset(x,y,sizeof(x)) #define For(i,j,k) for(int i=j;i<=k;i++) #define Rof(i,j,k) for(int i=j;i>=k;i--) #define Fe(x,y) for(int x=head[y];x;x=e[x].nxt) #define ckmx(a,b) a=max(a,b) #define ckmn(a,b) a=min(a,b) #define fin(s) freopen(s,"r",stdin) #define fout(s) freopen(s,"w",stdout) #define file(s) fin(s".in");fout(s".out") #define debug cerr<<"Passed line #"<<__LINE__<<endl #define numlim(s) cerr<<numeric_limits<s>::min()<<"~"<<numeric_limits<s>::max()<<endl #define ll long long const ll mod=1000000007; inline ll pw(ll x,ll y){ll r=1;while(y){if(y&1)r=r*x%mod;x=x*x%mod;y>>=1;}return r;} inline void mad(ll &a,ll b){a=(a+b)%mod;while(a<0)a+=mod;} inline void mmu(ll &a,ll b){a=(a*b)%mod;while(a<0)a+=mod;} #define inv(a) pw(a,mod-2) #define int long long #define N 170010 #define V 2000001 #define low (x&(-x)) int n=0,lim,ans[N],c[V],buf[V],tot=0; bool vis[V]; inline void add(int x,int y){ while(x<=lim){ c[x]+=y; if(!vis[x]){ vis[x]=1; buf[++tot]=x; } x+=low; } } inline int que(int x){ int res=0; while(x){ res+=c[x]; x-=low; } return res; } inline void clear(){ int x; while(tot){ x=buf[tot--]; vis[x]=0; c[x]=0; } } struct Que{ bool opt;//0 add 1 que int x,y,k,co; friend bool operator<(Que x,Que y){ if(x.x!=y.x) return x.x<y.x; if(x.y!=y.y) return x.y<y.y; return x.opt<y.opt; } }b[4*N];//询问是要 *4 的 int bt; struct Node{ bool opt; int x,y,xx,yy,k; }a[N]; #define mid ((l+r)>>1) void work(int l,int r){ if(l==r) return ; work(l,mid); bt=0; For(i,l,mid) if(!a[i].opt) b[++bt]=(Que){0,a[i].x,a[i].y,a[i].k,0}; For(i,mid+1,r) if(a[i].opt){ b[++bt]=(Que){1,a[i].xx ,a[i].yy ,i, 1}; b[++bt]=(Que){1,a[i].xx ,a[i].y-1,i,-1}; b[++bt]=(Que){1,a[i].x-1,a[i].yy ,i,-1}; b[++bt]=(Que){1,a[i].x-1,a[i].y-1,i, 1}; } sort(b+1,b+1+bt); For(i,1,bt) if(!b[i].opt) add(b[i].y,b[i].k); else ans[b[i].k]+=b[i].co*que(b[i].y); clear(); work(mid+1,r); } int32_t main(){IOS; int x; cin>>x>>lim; while(1){ cin>>x; if(x==3) break; n++; a[n].opt=x-1; if(!a[n].opt) cin>>a[n].x>>a[n].y>>a[n].k; else cin>>a[n].x>>a[n].y>>a[n].xx>>a[n].yy; } work(1,n); For(i,1,n) if(a[i].opt) cout<<ans[i]<<endl; return 0;}
P2487 [SDOI2011]拦截导弹
也类似模板,但是要算概率,直接古典概型上即可。
点击查看代码
//We'll be counting stars. //#pragma GCC optimize("Ofast") #include<bits/stdc++.h> using namespace std; #define IOS ios::sync_with_stdio(false) #define fir first #define sec second #define mkp make_pair #define pb emplace_back #define mem(x,y) memset(x,y,sizeof(x)) #define For(i,j,k) for(int i=j;i<=k;i++) #define Rof(i,j,k) for(int i=j;i>=k;i--) #define Fe(x,y) for(int x=head[y];x;x=e[x].nxt) #define ckmx(a,b) a=max(a,b) #define ckmn(a,b) a=min(a,b) #define fin(s) freopen(s,"r",stdin) #define fout(s) freopen(s,"w",stdout) #define file(s) fin(s".in");fout(s".out") #define debug cerr<<"Passed line #"<<__LINE__<<endl #define numlim(s) cerr<<numeric_limits<s>::min()<<"~"<<numeric_limits<s>::max()<<endl #define int long long #define db double #define N 50010 #define pi pair<int,db> struct Node{ int x,y,id; friend bool operator<(Node x,Node y){return x.id<y.id;} }a[N]; inline bool cmp(Node x,Node y){return x.x==y.x?x.id<y.id:x.x>y.x;} int n,s[N],lim,st[N],tot=0; struct node{ int mxlen; db cnt; void init(){mxlen=cnt=1;} void clear(){mxlen=-1;cnt=0;} friend node operator+(node x,node y){ if(x.mxlen==y.mxlen) return (node){x.mxlen,x.cnt+y.cnt}; else return x.mxlen>y.mxlen?x:y; } friend void operator+=(node &x,node y){x=x+y;} }t[N<<2],f[2][N]; void lisan(){//lisan for a.y For(i,1,n) s[i]=a[i].y; sort(s+1,s+1+n); lim=unique(s+1,s+1+n)-s-1; For(i,1,n) a[i].y=lower_bound(s+1,s+1+lim,a[i].y)-s; } #define mid ((l+r)>>1) #define ls (rt<<1) #define rs (rt<<1|1) void build(int rt,int l,int r){ t[rt].clear(); if(l==r) return ; build(ls,l,mid); build(rs,mid+1,r); } void add(int rt,int l,int r,int x,node val){ if(l==r){ // cout<<t[rt].mxlen<<" "<<t[rt].cnt<<endl; t[rt]+=val; st[++tot]=rt; // cout<<x<<"!"<<val.mxlen<<" "<<val.cnt<<" "<<t[rt].mxlen<<" "<<t[rt].cnt<<endl; return ; } if(x<=mid) add(ls,l,mid,x,val); else add(rs,mid+1,r,x,val); t[rt]=t[ls]+t[rs]; } node que(int rt,int l,int r,int x,int y){ if(l==x && r==y) return t[rt]; if(y<=mid) return que(ls,l,mid,x,y); else if(x>mid) return que(rs,mid+1,r,x,y); return que(ls,l,mid,x,mid)+que(rs,mid+1,r,mid+1,y); } void clear(){ int x; while(tot){ x=st[tot--]; while(x && t[x].mxlen!=-1){ t[x].clear(); x>>=1; } } } node addlen(node x){x.mxlen++;return x;} void solve(int l,int r){ if(l==r) return ; // cout<<"solve "<<l<<"~"<<r<<endl; solve(l,mid); sort(a+l,a+r+1,cmp); // cout<<"mid "<<l<<"~"<<r<<" "; For(i,l,r) cout<<a[i].id<<" "; cout<<endl; For(i,l,r) if(a[i].id<=mid) add(1,1,lim,a[i].y,f[0][a[i].id]); else f[0][a[i].id]+=addlen(que(1,1,lim,a[i].y,lim)); clear(); sort(a+l,a+r+1); solve(mid+1,r); // cout<<"end "<<l<<"~"<<r<<" "; For(i,l,r) cout<<f[0][i].mxlen<<" "; cout<<endl; } int32_t main(){IOS; cin>>n; For(i,1,n) cin>>a[i].x>>a[i].y; lisan(); build(1,1,lim); cout<<fixed<<setprecision(5); For(i,1,n) f[0][i].init(); reverse(a+1,a+1+n); For(i,1,n) a[i].x*=-1; For(i,1,n) a[i].y=lim-a[i].y+1; For(i,1,n) a[i].id=i; solve(1,n); For(i,1,n) f[1][i]=f[0][n-i+1]; For(i,1,n) f[0][i].init(); reverse(a+1,a+1+n); For(i,1,n) a[i].x*=-1; For(i,1,n) a[i].y=lim-a[i].y+1; For(i,1,n) a[i].id=i; // For(i,1,n) cout<<a[i].x<<" "<<a[i].y<<" "<<a[i].id<<endl; solve(1,n); // For(i,1,n) cout<<f[0][i].mxlen<<">"<<f[0][i].cnt<<endl; // For(i,1,n) cout<<f[1][i].mxlen<<"<"<<f[1][i].cnt<<endl; int ans=0; db sum=0; For(i,1,n) ckmx(ans,f[0][i].mxlen); cout<<ans<<endl; For(i,1,n) if(f[0][i].mxlen==ans) sum+=f[0][i].cnt; For(i,1,n) if(f[0][i].mxlen+f[1][i].mxlen-1<ans) cout<<(db)0<<" "; else cout<<f[0][i].cnt*f[1][i].cnt/sum<<" "; cout<<endl; return 0;}
P4169 [Violet]天使玩偶/SJY摆棋子
不是那个 sjy
发现哈密尔顿距离不好搞,我们将绝对值拆开,每次询问拆成左下左上右下右上四个子问题的最小值。
那和 P4390 [BOI2007]Mokia 摩基亚 不就类似了?
点击查看代码
//We'll be counting stars. #include<bits/stdc++.h> using namespace std; #define For(i,j,k) for(int i=j;i<=k;i++) #define Rof(i,j,k) for(int i=j;i>=k;i--) #define ckmx(a,b) a=max(a,b) #define ckmn(a,b) a=min(a,b) #define N 600010 #define V 1000002 #define low (x&(-x)) const int inf=1e7; int c[V],buf[N],bt=0; void add(int x,int y){ buf[++bt]=x; while(x<V){ ckmx(c[x],y); x+=low; } } int que(int x){ int res=0; while(x){ ckmx(res,c[x]); x-=low; } return res; } void clear(){ int x; while(bt){ x=buf[bt--]; while(x<V){ c[x]=0; x+=low; } } } struct node{ bool opt; int x,y; }a[N]; struct Node{ bool opt; int x,y,id; friend bool operator<(Node x,Node y){return x.x!=y.x?x.x<y.x:(x.y!=y.y?x.y<y.y:x.opt<y.opt);} }b[N]; int n,m,f[N],tot; void solve(int l,int r){ if(l==r) return ; int x,mid=(l+r)>>1; solve(l,mid); tot=0; For(i,l,mid) if(!a[i].opt) b[++tot]=(Node){a[i].opt,a[i].x,a[i].y,i}; For(i,mid+1,r) if(a[i].opt) b[++tot]=(Node){a[i].opt,a[i].x,a[i].y,i}; sort(b+1,b+1+tot); For(i,1,tot) if(!b[i].opt) add(b[i].y,b[i].x+b[i].y); else x=que(b[i].y),ckmn(f[b[i].id],x?b[i].x+b[i].y-x:inf); clear(); solve(mid+1,r); } int32_t main(){ scanf("%d%d",&n,&m); For(i,1,n) scanf("%d%d",&a[i].x,&a[i].y); For(i,1,n) a[i].opt=0; int x; For(i,n+1,n+m){ scanf("%d%d%d",&x,&a[i].x,&a[i].y); a[i].opt=x-1; } n+=m; For(i,1,n) a[i].x++; For(i,1,n) a[i].y++; For(i,1,n) f[i]=inf; solve(1,n); For(i,1,n) a[i].x=V+1-a[i].x; solve(1,n); For(i,1,n) a[i].y=V+1-a[i].y; solve(1,n); For(i,1,n) a[i].x=V+1-a[i].x; solve(1,n); For(i,1,n) if(a[i].opt) printf("%d\n",f[i]); return 0;}
本文来自博客园,作者:ShaoJia,版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义