对于能用cdq分治的题目需要满足3个条件
可以离线
修改不会相互影响
询问不会相互影响
归并排序求逆序对以及二维偏序很好的对cdq分治做了一个样例
这里就不在赘述
cdq分治处理单点修改,区间查询,可离线
首先,单点修改,区间查询,可离线,刚好满足cdq分治的使用要求
那么考虑怎么用cdq分治的思想解决这个问题
考虑现在有两段操作 依次按照 操作序号的大小以及先修改再查询有序
对于为什么每次只处理左端的修改,以及右端的询问,可以通过一张图来看
比如说,我现在有个询问,在划圈处
很显然,有两段对他做了操作
在比如对于一个修改,他能影响的范围如图
蓝色部分是他的修改范围
可以浅显的认为 cdq分治就是对于操作的的范围做的处理,使得操作不漏不多(比较妙)但我这个沙茶是学不会的啦
#include<bits/stdc++.h>
#define MAXN 700005
typedef long long ll;
using namespace std;
int n,m,tot,js,ans[MAXN];
struct node{
int tp,val,id;
}t[MAXN * 3] , t2[MAXN * 3];
bool operator < (node x , node y){
return ((x.id == y.id) ? (x.tp < y.tp) : (x.id < y.id));
}
void init(){
cin>>n>>m;
for(int i = 1 ; i <= n ; i++){
tot++;
t[tot].tp = 1;
cin>>t[tot].val;
t[tot].id = i;
}
int x,y,z;
for(int i = 1 ; i <= m ; i++){
cin>>x;
if(x == 1){
tot++;
t[tot].tp = 1;
cin>>t[tot].id;
cin>>t[tot].val;
}
else{
tot++ , js++;
t[tot].tp = 2;
t[tot].val = js;
cin>>t[tot].id;
t[tot].id--;
tot++;
t[tot].tp = 3;
t[tot].val = js;
cin>>t[tot].id;
}
}
}
void solve(int l , int r){
if(l == r)return;
int mid = (l + r) >> 1;
int l1 = l , l2 = mid + 1 , len = l;
solve(l , mid) , solve(mid + 1 , r);
ll sum = 0;
while(l1 <= mid && l2 <= r){
if(t[l1] < t[l2]){
if(t[l1].tp == 1)sum = sum + t[l1].val;
t2[len] = t[l1] , len++ , l1++;
}
else{
if(t[l2].tp == 2)ans[t[l2].val] -= sum;
if(t[l2].tp == 3)ans[t[l2].val] += sum;
t2[len] = t[l2] , len++ , l2++;
}
}
while(l1 <= mid){
if(t[l1].tp == 1)sum = sum + t[l1].val;
t2[len] = t[l1] , len++ , l1++;
}
while(l2 <= r){
if(t[l2].tp == 2)ans[t[l2].val] -= sum;
if(t[l2].tp == 3)ans[t[l2].val] += sum;
t2[len] = t[l2] , len++ , l2++;
}
for(int i = l ; i <= r ; i++)t[i] = t2[i];
}
int main(){
init();
solve(1 , tot);
for(int i = 1 ; i <= js ; i++)cout<<ans[i]<<endl;
}
P3810 【模板】三维偏序(陌上花开)
结合魔板,成功A掉这个题。。。我这屑人就这样了
有个关键点,cdq分治不能有重复元素
#include<bits/stdc++.h>
#define MAXN 900005
using namespace std;
int n,k,q[MAXN],ans[MAXN],tot,cnt[MAXN];
struct node{
int a,b,c,id;
}t[MAXN],t2[MAXN];
bool cmp(node x , node y){
return ((x.a == y.a) ? (((x.b == y.b) ? (x.c < y.c) : (x.b < y.b))) : (x.a < y.a));
}
int lowbit(int x){
return x & (-x);
}
int que(int x){
int zz = 0;
while(x){
zz += q[x];
x = x - lowbit(x);
}
return zz;
}
void clear(int x){
while(x <= k){
q[x] = 0;
x += lowbit(x);
}
}
void update(int x , int y){
while(x <= k){
q[x] += y;
x = x + lowbit(x);
}
}
void solve(int l , int r){
if(l == r)return;
int mid = (l + r) >> 1 , l1 = l , l2 = mid + 1 , len = l;
solve(l , mid) , solve(mid + 1 , r);
while(l1 <= mid && l2 <= r){
if(t[l1].b <= t[l2].b){
update(t[l1].c , cnt[t[l1].id]);
t2[len] = t[l1] , len++ , l1++;
}
else{
ans[t[l2].id] = ans[t[l2].id] + que(t[l2].c);
t2[len] = t[l2] , len++ , l2++;
}
}
while(l1 <= mid){
t2[len] = t[l1] , len++ , l1++;
}
while(l2 <= r){
ans[t[l2].id] = ans[t[l2].id] + que(t[l2].c);
t2[len] = t[l2] , len++ , l2++;
}
for(int i = l ; i <= r ; i++)t[i] = t2[i];
for(int i = l ; i <= r ; i++)clear(t[i].c);
}
int main(){
// freopen("P3810_2.in" , "r" , stdin);
// freopen("out.txt" , "w" , stdout);
cin>>n>>k;
for(int i = 1 ; i <= n ; i++)cin>>t2[i].a>>t2[i].b>>t2[i].c;
sort(t2 + 1 , t2 + 1 + n , cmp);
for(int i = 1 ; i <= n ; i++){
if(t2[i].a != t[tot].a || t2[i].b != t[tot].b || t2[i].c != t[tot].c){
tot++ , t[tot] = t2[i] , cnt[tot] = 1 , t[tot].id = tot;
}
else cnt[tot]++;
}
for(int i = 1 ; i <= tot ; i++)ans[i] = cnt[i] - 1;
sort(t + 1 , t + 1 + tot , cmp);
solve(1 , tot);
memset(q , 0 ,sizeof(q));
for(int i = 1 ; i <= tot ; i++)q[ans[i]] += cnt[i];
for(int i = 0 ; i < n ; i++)cout<<q[i]<<endl;
}