cdq分治解决偏序与整体二分解决区间k小思路相似,都是考虑左区间对右区间的影响,但是实现略有不同
偏序的重点是:理解两个有序链表的合并,即,一次归并排序
整体二分的重点是:二分权值,把操作(查询与修改)划分到左右区间,然后递归处理
陌上花开
x排序,y分治,z树状数组
/*author:revolIA*/
#include
using namespace std;
typedef long long ll;
const int maxn = 2e5+7;
int Tree[maxn],n,k;
int out[maxn];
void Add(int x,int val){
for(;x<=k;x+=x&-x)Tree[x] += val;
}
int query(int x,int ans = 0){
for(;x;x-=x&-x)ans += Tree[x];
return ans;
}
struct node{
int x,y,z;
int ans,w;
bool operator < (const node &T)const{
if(x != T.x)return x>1;
CDQ(l,mid),CDQ(mid+1,r);
int L = l,R = mid+1,cnt = l;
while(L<=mid && R<=r){
if(Qt[L].y<=Qt[R].y){
Add(Qt[L].z,Qt[L].w);
Tmp[cnt++] = Qt[L++];
}else{
Qt[R].ans += query(Qt[R].z);
Tmp[cnt++] = Qt[R++];
}
}
while(R<=r){
Qt[R].ans += query(Qt[R].z);
Tmp[cnt++] = Qt[R++];
}
for(int i=l;i
cogs577.蝗灾
统计矩阵内点数(可带权)
/*author:revolIA*/
#include
using namespace std;
typedef long long ll;
const int maxn = 1e6+7;
int Tree[maxn],ans[maxn],w,n,cnt,tot;
void add(int x,int val){while(x<=w)Tree[x] += val,x+=x&-x;}
int query(int x,int ans = 0){while(x)ans += Tree[x],x-=x&-x;return ans;}
struct node{
int x,y,w;
int pos,opt;
}Qt[maxn],Tmp[maxn];
void CDQ(int l,int r){
if(l == r)return;
int mid = l+r>>1;
CDQ(l,mid),CDQ(mid+1,r);
int L = l,R = mid+1,cnt = l;
while(L<=mid && R<=r){
if(Qt[L].x <= Qt[R].x){
if(!Qt[L].opt)add(Qt[L].y,Qt[L].w);
Tmp[cnt++] = Qt[L++];
}else{
if(Qt[R].opt == 1)ans[Qt[R].pos] -= query(Qt[R].w)-query(Qt[R].y-1);
if(Qt[R].opt == 2)ans[Qt[R].pos] += query(Qt[R].w)-query(Qt[R].y-1);
Tmp[cnt++] = Qt[R++];
}
}
while(R<=r){
if(Qt[R].opt == 1)ans[Qt[R].pos] -= query(Qt[R].w)-query(Qt[R].y-1);
if(Qt[R].opt == 2)ans[Qt[R].pos] += query(Qt[R].w)-query(Qt[R].y-1);
Tmp[cnt++] = Qt[R++];
}
for(int i=l;iz)swap(x,z);
if(y>opt)swap(y,opt);
Qt[++cnt] = {x-1,y,opt,tot,1};
Qt[++cnt] = {z,y,opt,tot,2};
}
}
CDQ(1,cnt);
for(int i=1;i<=tot;i++)printf("%d\n",ans[i]);
return 0;
}
整体二分,静态区间第k小(主席树)
洛谷p3834
/*author:revolIA*/
#include
using namespace std;
typedef long long ll;
const int maxn = 4e5+7,inf = 1e9+7;
int Tree[maxn],n,m;
int ans[maxn];
void Add(int x,int val){
for(;x<=n;x+=x&-x)Tree[x] += val;
}
int query(int x,int ans = 0){
for(;x;x-=x&-x)ans += Tree[x];
return ans;
}
struct node{
int x,y,k;
int pos,opt;
}Qt[maxn],Tmp[maxn];
void CDQ(int l,int r,int L,int R){
if(l>r || L>R)return;
if(l == r){
for(int i=L;i<=R;i++)if(Qt[i].opt){
ans[Qt[i].pos] = l;
}
return;
}
int mid = (l+r)>>1;
int cnl = L,cnr = R;
for(int i=L;i<=R;i++){
if(Qt[i].opt){
int sum = query(Qt[i].y)-query(Qt[i].x-1);
if(sumx?Mr:x;
}
for(int i=1,x,y,k;i<=m;i++){
scanf("%d%d%d",&x,&y,&k);
Qt[i+n] = {x,y,k,i,1};
}
CDQ(Ml,Mr,1,n+m);
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}
整体二分,动态区间k小(带修主席树)
Zoj2112.Dynamic Rankings
/*author:revolIA*/
#include
using namespace std;
typedef long long ll;
const int maxn = 4e5+7,inf = 1e9+7;
int Tree[maxn],n,m,a[maxn];
int ans[maxn],tot,cnt;
void Add(int x,int val){
for(;x<=n;x+=x&-x)Tree[x] += val;
}
int query(int x,int ans = 0){
for(;x;x-=x&-x)ans += Tree[x];
return ans;
}
struct node{
int x,y,k;
int pos,opt;
}Qt[maxn],Tmp[maxn];
void CDQ(int l,int r,int L,int R){
if(l>r || L>R)return;
if(l == r){
for(int i=L;i<=R;i++)if(Qt[i].opt>0){
ans[Qt[i].pos] = l;
}
return;
}
int mid = (l+r)>>1;
int cnl = L,cnr = R;
for(int i=L;i<=R;i++){
if(Qt[i].opt>0){
int sum = query(Qt[i].y)-query(Qt[i].x-1);
if(sumx?Mr:x;
}
for(int i=1,x,y,k;i<=m;i++){
scanf("%s",opt);
if(opt[0] == 'Q'){
scanf("%d%d%d",&x,&y,&k);
Qt[++cnt] = {x,y,k,++tot,1};//ask
}else{
scanf("%d%d",&x,&y);
Qt[++cnt] = {a[x],0,0,x,-1};//delete
Qt[++cnt] = {y,0,0,x,0};//insert
a[x] = y;
}
}
CDQ(Ml,Mr,1,cnt);
for(int i=1;i<=tot;i++)printf("%d\n",ans[i]),ans[i] = 0;
}
return 0;
}