重修 CDQ 分治

简介

把动态问题转化为静态问题。

静态问题:没有修改操作的问题,或者所有查询操作都在修改操作之后的问题

动态问题:修改和查询操作交叉的问题

CDQ+log

例题

P3810 【模板】三维偏序(陌上花开)

就是个模板。

P4390 [BOI2007]Mokia 摩基亚

我们按照时间分治 solve(l,r)

  1. solve(l,mid),因为时间无后效性。

  2. 再计算 [l,mid] 的加点操作给 [mid+1,r] 的贡献。

  3. 最后,由于 [l,mid][mid+1,r] 的贡献已经算完,直接放心 solve(mid+1,r)

所以这层分治之内唯一要解决的就是第二步。

求矩形和可以二维差分转化为四个 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;}
posted @   ShaoJia  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示