[BZOJ 1176:单点修改,查询子矩阵和]:

1176: [Balkan2007]Mokia

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 2005  Solved: 894
[Submit][Status][Discuss]

Description

维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.

Input

第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

接下来每行为一下三种输入之一(不包含引号):

"1 x y a"

"2 x1 y1 x2 y2"

"3"

输入1:你需要把(x,y)(第x行第y列)的格子权值增加a

输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出

输入3:表示输入结束

Output

对于每个输入2,输出一行,即输入2的答案

Sample Input

0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3

Sample Output

3
5

HINT

保证答案不会超过int范围

Source

分析:

第一道CDQ分治的题目TAT...

查询的限制——序

对于一个数据结构题而言(或者需要运用数据结构的地方),我们无非就是做两件操作,一是修改,二是查询 
对于修改而言,有插入删除变更(其实等价于删除再插入)这几种方式 
那么查询的本质是什么呢 
我们思考所遇到过的数据结构题,可以发现查询实际上就在做一件事情: 
符合本次查询的限制的修改对答案产生的效果合并起来 
满足这种限制通常表现为一种的要求,并且这种序是广义的,符合限制的操作往往是按某种序(或多种序)排序后的操作的前缀 
通常来说,查询一定有时间上的限制,也就是要求考虑发生在某个时刻之前的所有查询,对于一个问题而言,假如所有查询要求的发生时刻相同,那这就是一个静态查询问题,如果要求发生的时刻随着查询而变,那这就是一个动态修改问题,动态修改问题较静态查询而言复杂很多,往往需要高级数据结构,可持久化等手段,而静态查询简单很多,例如时间倒流,twopointers之类的方法都是很好的选择

我理解的CDQ分治就是通过离线去掉时间的限制(或者某一维的限制),把动态修改问题转化为静态查询问题...

对于这道题来说,我们可以把查询操作分为4个询问前缀和的操作...

我们把所有的操作按照x排序,那么我们查询的时候维护y的树状数组就可以...这样达到了降维的目的...

我们把操作按照x排序,然后对于当前操作区间[l,r],可以应用分治的思想,把区间按照时间为关键字分为[l,mid]和[mid+1,r]两个区间(在两个区间内x依然有序),对于区间内部的修改操作对查询操作的影响,这是一个相同的子问题,所以我们递归解决即可...我们只需要处理的就是[l,mid]中的修改操作对[mid+1,r]中的查询操作的影响...这个树状数组处理即可...

代码:

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
using namespace std;
//大鹏一日同风起,扶摇直上九万里 const int maxn=+,maxm=+; struct M{
int x,y,val,pos,ans;
M() {}
M(int a,int b,int c,int d);
}q[maxm],q2[maxm]; int n,m,op,T,tr[maxn],tim[maxn]; M :: M(int a=,int b=,int c=,int d=){
x=a,y=b,val=c,pos=d,ans=;
} inline void insert(int x,int y){
for(;x<=n;x+=x&(-x)){
if(tim[x]!=T)
tr[x]=;
tim[x]=T,tr[x]+=y;
}
} inline int query(int x){
int res=;
for(;x;x-=x&(-x))
if(tim[x]==T)
res+=tr[x];
return res;
} inline bool cmp1(M a,M b){
return a.x<b.x;
} inline bool cmp2(M a,M b){
return a.pos<b.pos;
} inline void CDQ(int l,int r){
if(l==r)
return;
int mid=(l+r)>>,l1=l,l2=mid+;
for(int i=l;i<=r;i++){
if(q[i].pos<=mid)
q2[l1++]=q[i];
else
q2[l2++]=q[i];
}
memcpy(q+l,q2+l,sizeof(q[])*(r-l+));CDQ(l,mid);
int j=l;T++;
for(int i=mid+;i<=r;i++){
for(;q[j].x<=q[i].x&&j<=mid;j++)
if(q[j].val!=)
insert(q[j].y,q[j].val);
if(q[i].val==)
q[i].ans+=query(q[i].y);
}
CDQ(mid+,r);
l1=l,l2=mid+;
for(int i=l;i<=r;i++){
if((q[l1].x<q[l2].x&&l1<=mid)||l2>r)
q2[i]=q[l1++];
else
q2[i]=q[l2++];
}
memcpy(q+l,q2+l,sizeof(q[])*(r-l+));
} signed main(void){
int l,s,x,y;m=;
scanf("%d%d",&n,&n);
while(scanf("%d",&op)&&op!=){
if(op==)
scanf("%d%d%d",&x,&y,&s),q[++m]=M(x,y,s,m);
else
scanf("%d%d%d%d",&l,&s,&x,&y),
q[++m]=M(l-,s-,,m),
q[++m]=M(l-,y ,,m),
q[++m]=M(x ,s-,,m),
q[++m]=M(x ,y ,,m);
}
sort(q+,q+m+,cmp1);CDQ(,m);sort(q+,q+m+,cmp2);
for(int i=,lala;i<=m;i++)
if(q[i].val==){
lala =q[i++].ans;
lala-=q[i++].ans;
lala-=q[i++].ans;
lala+=q[i ].ans;
printf("%d\n",lala);
}
return ;
}//Cap ou pas cap. Cap.

[BZOJ 3163:背包问题]:

3163: [Heoi2013]Eden的新背包问题

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 382  Solved: 252
[Submit][Status][Discuss]

Description

“寄没有地址的信,这样的情绪有种距离,你放着谁的歌曲,是怎样的心心静,能不能说给我听。”
失忆的Eden总想努力地回忆起过去,然而总是只能清晰地记得那种思念的感觉,却不能回忆起她的音容笑貌。 记忆中,她总是喜欢给Eden出谜题:在 valentine’s day 的夜晚,两人在闹市中闲逛时,望着礼品店里精巧玲珑的各式玩偶,她突发奇想,问了 Eden这样的一个问题:有n个玩偶,每个玩偶有对应的价值、价钱,每个玩偶都可以被买有限次,在携带的价钱m固定的情况下,如何选择买哪些玩偶以及每个玩偶买多少个,才能使得选择的玩偶总价钱不超过m,且价值和最大。众所周知的,这是一个很经典的多重背包问题,Eden很快解决了,不过她似乎因为自己的问题被飞快解决感到了一丝不高兴,于是她希望把问题加难:多次 询问,每次询问都将给出新的总价钱,并且会去掉某个玩偶(即这个玩偶不能被选择),再问此时的多重背包的答案(即前一段所叙述的问题)。  
这下Eden 犯难了,不过Eden不希望自己被难住,你能帮帮他么?

Input

第一行一个数n,表示有n个玩偶,玩偶从0开始编号 
第二行开始后面的 n行,每行三个数 ai, bi, c i,分别表示买一个第i个玩偶需
要的价钱,获得的价值以及第i个玩偶的限购次数。 
接下来的一行为q,表示询问次数。 
接下来q行,每行两个数di. ei表示每个询问去掉的是哪个玩偶(注意玩偶从0开始编号)以及该询问对应的新的总价钱数。(去掉操作不保留,即不同询问互相独立)

Output

输出q行,第i行输出对于第 i个询问的答案。

Sample Input

5
2 3 4
1 2 1
4 1 2
2 1 1
3 2 3
5
1 10
2 7
3 4
4 8
0 5

Sample Output

13
11
6
12
4

HINT

一共五种玩偶,分别的价钱价值和限购次数为 (2,3,4), (1,2,1), (4,1,2), (2,1,1),(3,2,3)。五个询问,以第一个询问为例。第一个询问表示的是去掉编号为1的玩偶,且拥有的钱数为10时可以获得的最大价值,则此时剩余玩偶为(2,3,4),(4,1,2),(2,1,1),(3,2,3),若把编号为0的玩偶买4个(即全买了),然后编号为3的玩偶买一个,则刚好把10元全部花完,且总价值为13。可以证明没有更优的方案了。注意买某种玩偶不一定要买光。

100. 数据满足1 ≤ n ≤ 1000, 1 ≤ q ≤ 3*105 , 1 ≤  a

i、bi、c i ≤ 100, 0 ≤ d i < n,  0  ≤ei ≤ 1000。

Source

分析:

对于删除物品分治...

我们定义CDQ(l,r)为删除[l,r]这个区间的物品的dp值,那么递归到[l,l]的时候就可以更新答案了...

怎么计算...因为[l,mid]的dp值一定包含了[mid+1,r]之间的物品,所以我们可以用[mid+1,r]之间的物品更新dp值之后传入[l,mid]进行计算,同理,用[l,mid]的物品更新dp值然后传入[mid+1,r]进行计算...

其实为了保证复杂度要用单调队列优化背包...但是这题数据水...我很懒...

代码:

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
using namespace std;
//大鹏一日同风起,扶摇直上九万里 const int maxn=+,maxq=+; int n,m,cnt,v[maxq],co[maxn],hd[maxn],ans[maxq],pos[maxq],nxt[maxq],val[maxn],num[maxn],f[][maxn]; inline void add(int s,int x,int y){
pos[cnt]=y;v[cnt]=s;nxt[cnt]=hd[x];hd[x]=cnt++;
} inline void dp(int *f,int x){
for(int i=;i<=num[x];i++)
for(int j=maxn-;j>=co[x];j--)
f[j]=max(f[j],f[j-co[x]]+val[x]);
} inline void CDQ(int l,int r,int d){
if(l==r){
for(int i=hd[l];i!=-;i=nxt[i])
ans[pos[i]]=f[d-][v[i]];
return;
}
int mid=(l+r)>>;
for(int i=;i<maxn;i++)
f[d][i]=f[d-][i];
for(int i=mid+;i<=r;i++)
dp(f[d],i);
CDQ(l,mid,d+);
for(int i=;i<maxn;i++)
f[d][i]=f[d-][i];
for(int i=l;i<=mid;i++)
dp(f[d],i);
CDQ(mid+,r,d+);
} signed main(void){
scanf("%d",&n);cnt=;
memset(hd,-,sizeof(hd));
for(int i=;i<=n;i++)
scanf("%d%d%d",&co[i],&val[i],&num[i]);
scanf("%d",&m);
for(int i=,x,y;i<=m;i++)
scanf("%d%d",&x,&y),add(y,x+,i);
CDQ(,n,);
for(int i=;i<=m;i++)
printf("%d\n",ans[i]);
return ;
}//Cap ou pas cap. Cap.

[BZOJ 3237: 无向图是否联通]:

3237: [Ahoi2013]连通图

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1155  Solved: 396
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

4 5
1 2
2 3
3 4
4 1
2 4
3
1 5
2 2 3
2 1 2

Sample Output

Connected
Disconnected
Connected

HINT

N<=100000 M<=200000 K<=100000

Source

分析:

一开始想的是CDQ(l,r)代表的是删掉[l,r]这一整段区间的边无向图的状态,但是发现酱紫是不行滴...

然后我们发现我们可以对query进行分治,CDQ(l,r)代表的是去掉[l,r]这段询问的边无向图的状态...我们用并查集来维护...

学习到一个新的方法...用栈来维护并查集的压缩过程,这样可以回溯...

因为并查集没有按秩合并...所以被YSQ吐槽为“叽里咕噜滚雪球式并查集”...( ̄_ ̄|||)...

好吧...按秩合并确实快...4s和12s的差距TAT...

代码:

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
using namespace std;
//大鹏一日同风起,扶摇直上九万里 const int maxn=+,maxm=+; int n,m,Q,T,tail,fa[maxn],ans[maxn],stk[maxn*],vis[maxm]; struct M{
int num,id[];
}q[maxn]; struct G{
int x,y;
}e[maxm]; inline int find(int x){
if(fa[x]==x)
return x;
stk[++tail]=x;stk[++tail]=fa[x];
return fa[x]=find(fa[x]);
} inline void merge(int x,int y){
int fx=find(x),fy=find(y);
if(fx!=fy)
stk[++tail]=fx,stk[++tail]=fx,fa[fx]=fy;
} inline void CDQ(int l,int r){
int mid=(l+r)>>,lala=tail;
if(l==r){
for(int i=;i<=q[l].num&&ans[l];i++)
if(find(e[q[l].id[i]].x)!=find(e[q[l].id[i]].y))
ans[l]=;
while(lala!=tail)
fa[stk[tail-]]=stk[tail],tail-=;
return;
}T++;
for(int i=l;i<=mid;i++)
for(int j=;j<=q[i].num;j++)
vis[q[i].id[j]]=T;
for(int i=mid+;i<=r;i++)
for(int j=;j<=q[i].num;j++)
if(vis[q[i].id[j]]!=T)
merge(e[q[i].id[j]].x,e[q[i].id[j]].y);
CDQ(l,mid);T++;
while(lala!=tail)
fa[stk[tail-]]=stk[tail],tail-=;
for(int i=mid+;i<=r;i++)
for(int j=;j<=q[i].num;j++)
vis[q[i].id[j]]=T;
for(int i=l;i<=mid;i++)
for(int j=;j<=q[i].num;j++)
if(vis[q[i].id[j]]!=T)
merge(e[q[i].id[j]].x,e[q[i].id[j]].y);
CDQ(mid+,r);
while(lala!=tail)
fa[stk[tail-]]=stk[tail],tail-=;
} signed main(void){
scanf("%d%d",&n,&m);
memset(vis,-,sizeof(vis));
for(int i=;i<=m;i++)
scanf("%d%d",&e[i].x,&e[i].y);
scanf("%d",&Q);
for(int i=;i<=Q;i++){
scanf("%d",&q[i].num);ans[i]=;
for(int j=;j<=q[i].num;j++)
scanf("%d",&q[i].id[j]),vis[q[i].id[j]]=;
}
for(int i=;i<=n;i++)
fa[i]=i;
for(int i=;i<=m;i++)
if(vis[i]==-)
merge(e[i].x,e[i].y);
CDQ(,Q);
for(int i=;i<=Q;i++)
ans[i]?puts("Connected"):puts("Disconnected");
return ;
}//Cap ou pas cap. Cap.

[BZOJ 2001:动态最小生成树]:

2001: [Hnoi2010]City 城市建设

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 1129  Solved: 552
[Submit][Status][Discuss]

Description

PS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁。Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费。Louis希望建造最少的道路使得国内所有的城市连通。但是由于某些因素,城市之间修建道路需要的花费会随着时间而改变,Louis会不断得到某道路的修建代价改变的消息,他希望每得到一条消息后能立即知道使城市连通的最小花费总和, Louis决定求助于你来完成这个任务。

Input

文件第一行包含三个整数N,M,Q,分别表示城市的数目,可以修建的道路个数,及收到的消息个数。 接下来M行,第i+1行有三个用空格隔开的整数Xi,Yi,Zi(1≤Xi,Yi≤n, 0≤Zi≤50000000),表示在城市Xi与城市Yi之间修建道路的代价为Zi。接下来Q行,每行包含两个数k,d,表示输入的第k个道路的修建代价修改为d(即将Zk修改为d)。

Output

输出包含Q行,第i行输出得知前i条消息后使城市连通的最小花费总和。

Sample Input

5 5 3
1 2 1
2 3 2
3 4 3
4 5 4
5 1 5
1 6
1 1
5 3

Sample Output

14
10
9

HINT

【数据规模】 对于20%的数据, n≤1000,m≤6000,Q≤6000。 有20%的数据,n≤1000,m≤50000,Q≤8000,修改后的代价不会比之前的代价低。 对于100%的数据, n≤20000,m≤50000,Q≤50000。

Source

分析:

这道题的思想主要在于通过分治来缩小图的规模,从而降低复杂度...

我们定义CDQ(l,r)为处理[l,r]的询问...那么这个时候[1,l-1]的边已经固定了...

有一下两个操作:

No.1  合并必须边:

我们把[l,r]的边设为-inf,跑最小生成树,树边就是必须边...(原因自己YY)...

No.2  删除多余边:

我们把[l,r]的边设为+inf,跑最小生成树,非树边是多余边...

然后递归边界为[l,l]这个时候跑最小生成树然后加上合并的权值就是当前的ans...

讲道理...这题主要是细节...我调了好久...要了数据才过...(好吧其实数据没有什么用...看样例就100了...这没法调啊w(゚Д゚)w)

代码:

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
#define inf 0x3f3f3f3f
using namespace std; const int maxn=+,maxm=+; int n,m,Q,T,tail,fa[maxn],stk[maxn*],ver[],edg[],vis[maxm]; long long ans[maxm],val[],w[maxm]; struct M{
int x,y,w,flag,id;
friend bool operator < (M a,M b){
return a.w<b.w;
}
}G[][maxm],lala[maxm],lalala[maxm]; struct L{
int id,w;
}q[maxm]; inline int find(int x){
if(fa[x]==x)
return x;
stk[++tail]=x,stk[++tail]=fa[x];
return fa[x]=find(fa[x]);
} inline void merge(int x,int y){
int fx=find(x),fy=find(y);
if(fx!=fy)
stk[++tail]=fx,stk[++tail]=fx,fa[fx]=fy;
} inline long long kruskal(int d){
sort(lala+,lala+edg[d]+);long long res=;
for(int i=;i<=edg[d];i++){
int fx=find(lala[i].x),fy=find(lala[i].y);
if(fx!=fy)
merge(fx,fy),res+=w[lala[i].id],lala[i].flag=;
else
lala[i].flag=;
}
return res;
} inline void CDQ(int l,int r,int d){
int tmp=tail,ttmp;
if(l==r){
w[q[l].id]=q[l].w;
for(int i=;i<=edg[d-];i++)
lala[i]=G[d-][i],lala[i].w=w[G[d-][i].id];
ans[l]=kruskal(d-)+val[d-];
while(tmp!=tail)
fa[stk[tail-]]=stk[tail],tail-=;
return;
}
edg[d]=edg[d-],val[d]=val[d-],ver[d]=ver[d-];
int mid=(l+r)>>;T++;
for(int i=l;i<=r;i++)
vis[q[i].id]=T;
for(int i=;i<=edg[d];i++){
lala[i]=G[d-][i],lala[i].w=w[G[d-][i].id];
if(vis[G[d-][i].id]==T)
lala[i].w=-inf;
}
kruskal(d);
while(tmp!=tail)
fa[stk[tail-]]=stk[tail],tail-=;
int haha=edg[d];
for(int i=,j=;i<=haha;i++){
if(lala[i].flag&&lala[i].w!=-inf)
merge(lala[i].x,lala[i].y),ver[d]--,edg[d]--,val[d]+=w[lala[i].id];
else
lala[i].x=find(lala[i].x),lala[i].y=find(lala[i].y),G[d][++j]=lala[i],G[d][j].w=w[lala[i].id];
}ttmp=tail;
for(int i=;i<=edg[d];i++){
G[d][i].x=find(G[d][i].x),G[d][i].y=find(G[d][i].y);
lala[i]=G[d][i],lala[i].w=w[G[d][i].id];
if(vis[G[d][i].id]==T)
lala[i].w=inf;
}
kruskal(d);
while(ttmp!=tail)
fa[stk[tail-]]=stk[tail],tail-=;
haha=edg[d];
for(int i=,j=;i<=haha;i++){
if(!lala[i].flag&&lala[i].w!=inf)
edg[d]--;
else
lala[i].x=fa[lala[i].x],lala[i].y=fa[lala[i].y],G[d][++j]=lala[i];
}
CDQ(l,mid,d+),CDQ(mid+,r,d+);
while(tail!=tmp)
fa[stk[tail-]]=stk[tail],tail-=;
} signed main(void){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
scanf("%d%d%d",&n,&m,&Q);
memset(vis,,sizeof(vis));
for(int i=;i<=m;i++)
scanf("%d%d%d",&G[][i].x,&G[][i].y,&G[][i].w),G[][i].id=i,w[i]=G[][i].w;
for(int i=;i<=Q;i++)
scanf("%d%d",&q[i].id,&q[i].w);
for(int i=;i<=n;i++)
fa[i]=i;
edg[]=m,ver[]=n,CDQ(,Q,);
for(int i=;i<=Q;i++)
printf("%lld\n",ans[i]);
return ;
}//Cap ou pas cap. Cap.

[BZOJ2716 平面最近点]:

2716: [Violet 3]天使玩偶

Time Limit: 80 Sec  Memory Limit: 128 MB
Submit: 1476  Solved: 623
[Submit][Status][Discuss]

Description

Input

Output

分析:

和第一道题目是一样的,只不过是把求和变成了取max...

首先我们可以以当前询问的点为原点,把平面划分为4个部分,我们首先考虑左下角的点dis[i,j]=x[i]-x[j]+y[i]-y[j]=x[i]+y[i]-(x[j]+y[j])...

这样我们只需要查询当前点左下角的点x+y最大的点即可,那么还是按照x排序维护y的树状数组...

那么其他三个区域的点可以对称一下转化为左下角的点...

但是这题它卡常数...我人帅自带大常数TAT...T死了...

所以就把O(nlgn)的四个排序改成了四个memcpy...然后就A了QAQ...

代码:

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
#define inf 0x7fffffff
using namespace std;
//大鹏一日同风起,扶摇直上九万里 const int maxn=+,maxm=+; int n,m,T,Max,tr[maxm],tim[maxm],ans[maxm]; struct M{
int t,x,y,id;
bool operator <(const M &a)const{
if(x!=a.x)
return x<a.x;
return t<a.t;
}
}q[maxn],q2[maxn],l[maxn]; inline int read(void){
char ch=getchar();int f=,x=;
while(!(ch>=''&&ch<='')){
if(ch=='-')
f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
x=x*+ch-'',ch=getchar();
return f*x;
} inline void insert(int x,int y){
for(;x<=Max;x+=x&-x){
/*
if(tim[x]!=T)
tr[x]=-1;
tim[x]=T,tr[x]=max(tr[x],y);
*/
if(tim[x]!=T||tr[x]<y)
tr[x]=y,tim[x]=T;
}
} inline int query(int x){
int res=-;
for(;x;x-=x&-x)
if(tim[x]==T)
res=max(tr[x],res);
return res;
} /*
inline void CDQ(int l,int r){
if(l==r)
return;
int mid=(l+r)>>1,l1=l,l2=mid+1;
for(int i=l;i<=r;i++){
if(q[i].id<=mid)
q2[l1++]=q[i];
else
q2[l2++]=q[i];
}
for(int i=l;i<=r;i++)
q[i]=q2[i];
CDQ(l,mid);int j=l;T++;
for(int i=mid+1;i<=r;i++){
for(;q[j].x<=q[i].x&&j<=mid;j++)
if(q[j].t==1)
insert(q[j].y,q[j].x+q[j].y);
if(q[i].t==2){
int lala=query(q[i].y);
q[i].ans=lala==-1?q[i].ans:min(q[i].x+q[i].y-lala,q[i].ans);
}
}
CDQ(mid+1,r);
l1=l,l2=mid+1;
for(int i=l;i<=r;i++){
if((q[l1].x<q[l2].x&&l1<=mid)||l2>r)
q2[i]=q[l1++];
else
q2[i]=q[l2++];
}
for(int i=l;i<=r;i++)
q[i]=q2[i];
}
*/ inline void CDQ(int l,int r){
if(l==r)
return;
int mid=(l+r)>>,l1=l,l2=mid+;
CDQ(l,mid),CDQ(mid+,r);
for(int i=l;i<=r;i++){
if((l1<=mid&&q[l1]<q[l2])||l2>r)
q2[i]=q[l1++];
else
q2[i]=q[l2++];
}
for(int i=l;i<=r;i++)
q[i]=q2[i];
T++;
for(int i=l;i<=r;i++){
if(q[i].t==&&q[i].id>mid){
int lala=query(q[i].y);
ans[q[i].id]=lala==-?ans[q[i].id]:min(q[i].x+q[i].y-lala,ans[q[i].id]);
}
else if(q[i].t==&&q[i].id<=mid)
insert(q[i].y,q[i].x+q[i].y);
}
} signed main(void){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
n=read(),m=read();Max=;T=;m+=n;
for(int i=;i<=n;i++){
l[i].x=read()+,l[i].y=read()+,l[i].id=i,l[i].t=;
if(l[i].x>Max)
Max=l[i].x;
if(l[i].y>Max)
Max=l[i].y;
}
for(int i=n+;i<=m;i++){
l[i].t=read(),l[i].x=read()+,l[i].y=read()+,l[i].id=i,ans[i]=inf;
if(l[i].x>Max)
Max=l[i].x;
if(l[i].y>Max)
Max=l[i].y;
}
Max++; /*
sort(q+1,q+m+1);CDQ(1,m);
for(int i=1;i<=m;i++)
q[i].x=Max-q[i].x;
sort(q+1,q+m+1);CDQ(1,m);
for(int i=1;i<=m;i++)
q[i].y=Max-q[i].y;
sort(q+1,q+m+1);CDQ(1,m);
for(int i=1;i<=m;i++)
q[i].x=-(q[i].x-Max);
sort(q+1,q+m+1);CDQ(1,m);
*/ memcpy(q,l,sizeof(q));
CDQ(,m); memcpy(q,l,sizeof(q));
for(int i=;i<=m;i++)
q[i].x=Max-q[i].x;
CDQ(,m); memcpy(q,l,sizeof(q));
for(int i=;i<=m;i++)
q[i].y=Max-q[i].y;
CDQ(,m); memcpy(q,l,sizeof(q));
for(int i=;i<=m;i++)
q[i].x=Max-q[i].x,q[i].y=Max-q[i].y;
CDQ(,m); for(int i=n+;i<=m;i++)
if(l[i].t==)
printf("%d\n",ans[i]);
return ;
}//Cap ou pas cap. Cap.

By NeighThorn

初识CDQ分治的更多相关文章

  1. 浅谈CDQ分治与偏序问题

    初识CDQ分治 CDQ分治是一个好东西,一直听着dalao们说所以就去学了下. CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. ...

  2. 【教程】简易CDQ分治教程&学习笔记

    前言 辣鸡蒟蒻__stdcall终于会CDQ分治啦!       CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. CDQ分治的基 ...

  3. BZOJ 2683 简单题 ——CDQ分治

    [题目分析] 感觉CDQ分治和整体二分有着很本质的区别. 为什么还有许多人把他们放在一起,也许是因为代码很像吧. CDQ分治最重要的是加入了时间对答案的影响,x,y,t三个条件. 排序解决了x ,分治 ...

  4. HDU5618 & CDQ分治

    Description: 三维数点 Solution: 第一道cdq分治...感觉还是很显然的虽然题目不能再傻逼了... Code: /*=============================== ...

  5. HDU5322 Hope(DP + CDQ分治 + NTT)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5322 Description Hope is a good thing, which can ...

  6. BZOJ4170 极光(CDQ分治 或 树套树)

    传送门 BZOJ上的题目没有题面-- [样例输入] 3 5 2 4 3 Query 2 2 Modify 1 3 Query 2 2 Modify 1 2 Query 1 1 [样例输出] 2 3 3 ...

  7. BZOJ2683 简单题(CDQ分治)

    传送门 之前听别人说CDQ分治不难学,今天才知道果真如此.之前一直为自己想不到CDQ的方法二很不爽,今天终于是想出来了一道了,太弱-- cdq分治主要就是把整段区间分成两半,然后用左区间的值去更新右区 ...

  8. BNUOJ 51279[组队活动 Large](cdq分治+FFT)

    传送门 大意:ACM校队一共有n名队员,从1到n标号,现在n名队员要组成若干支队伍,每支队伍至多有m名队员,求一共有多少种不同的组队方案.两个组队方案被视为不同的,当且仅当存在至少一名队员在两种方案中 ...

  9. 【BZOJ-3262】陌上花开 CDQ分治(3维偏序)

    3262: 陌上花开 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1439  Solved: 648[Submit][Status][Discuss ...

随机推荐

  1. JAVAWEB贵美网上商城完整项目源码(SSH2)

    JAVAWEB贵美网上商城完整项目源码(SSH2) 贵美网上商城原是北大青鸟的一个内部项目,项目采用 struts2+spring4+hibernate4+MySQL等技术实现,数据库连接池采用c3p ...

  2. WEB前端--背景相关知识点总结

    一.背景(background) 它是单一属性 但是它衍生出很多的复合属性 background-color  背景色 background-image 背景图片 background-repeat ...

  3. python tornado websocket 实时日志展示

    一.主题:实时展示服务器端动态生成的日志文件 二.流程: 1. 客户端浏览器与服务器建立websocket 链接,服务器挂起保存链接实例,等待新内容触发返回动作 2. 日志服务器脚本循环去发现新内容, ...

  4. Atitit.atiagent  agent分销系统 代理系统 设计文档

    Atitit.atiagent  agent分销系统 代理系统 设计文档 1. 启动项目1 2. 首也2 3. 登录功能2 4. 用户中心2 5. 充值查询3 6. 授权下级代理4 7. 我的提成5 ...

  5. SQL SERVER 2008 R2数据库出现“远程过程调用失败”(0x800706be)错误,怎么办!!

    以前SQL Server 2008 不能登陆的时候,总是通过“计算机管理”→“SQL Server服务”更改一下,"SQL Server(MSSQLSERVER)". 可是现在出现 ...

  6. Snap.svg – 现代 Web 开发必备的 JavaScript SVG 库

    SVG 是一种很好的 Web 技术方案,可以用来创建互动,在任何大小的屏幕上都会很好看.与分辨率无关的矢量图形.而这里推荐的 Snap.svg 这个 JavaScript 可以让你像 jQuery 操 ...

  7. [deviceone开发]-do_SegmentView和do_SlideView联动的示例

    一.简介 示例展示do_SegmentView和do_SlideView联动的使用,这二个组件很常用,而且这个组合也非常常用,类似网易新闻的效果,上面滑动带动下面的slideview滑动,反过来也是. ...

  8. [deviceone开发]-一个固定列,可以上下左右滑动的表格示例

    一.简介 一个类型table的例子,第一列和第二列可以固定,剩下的后面的很多列都可以左右滑动,也可以上下滑动,这种需求一般是为了展示多列表格数据.这个例子是通过二大部分: 左边是一个普通的listvi ...

  9. JavaScript基本语法(三)

    上篇博文说到JS的运算符,这次说说JS程序流程控制. 1. 条件语句 if 语法: if(condition) statements1 else statement2 当括号里的条件成立的时候,执行i ...

  10. SharePoint 2013 图文开发系列之自定义字段

    SharePoint使用的优势,就在于开箱即用.快速搭建,SharePoint自身为我们提供了很多字段类型,已经很丰富了.但是,在实际应用中,我们还需要一些功能特殊的字段,下面,我们简单介绍下字段的开 ...