题解 P3374 【【模板】树状数组 1】
为什么泥萌欺负
泥萌都不写
这么好的二维偏序模板题怎么能没有
我们都知道,
那么合并的时候就只需要按照修改位置合并就好了
然后把询问操作拆成两个前缀查询,
至于具体实现,我们可以这么搞
struct Node{
int opt , id , v;
Node(int opt = 0 , id = 0 , v = 0) {}
};
#include<iostream>
#include<cstdio>
#define mid ((l + r) >> 1)
using namespace std;
const int MAXN = 5e5 + 5;
struct Node{
int opt , id , v;
Node(int opt = 0 , int id = 0 , int v = 0) : opt(opt) , id(id) , v(v) {}
#define opt(i) A[i].opt
#define id(i) A[i].id
#define v(i) A[i].v
};
int n , m , cnt , qry , ans[MAXN];
Node A[MAXN << 1] , tmp[MAXN << 1];
inline void insert(int opt , int id , int v) {A[++cnt] = Node(opt , id , v);}
void cdq(int l , int r) {
if(l >= r) return ;
cdq(l , mid); cdq(mid + 1 , r);
int pos1 = l , pos2 = mid + 1 , sum = 0;
for(int tot = l ; tot <= r ; ++tot) {
//pos1 入队
if((id(pos1) <= id(pos2) && pos1 <= mid) || pos2 > r) {
if(opt(pos1) == 1) //那么后面的所有询问操作都应该受到它的影响
sum += v(pos1);
//至于其它的opt,证明它是询问,一个询问对后面应该没有任何影响
tmp[tot] = A[pos1++];
}
//pos2 入队
else {
if(opt(pos2) == 2)//它入队了,证明后面的无论所有东西都对我没有任何关系了,因为id一定比我小,时间轴也在我后面,我肯定不会被那些修改而影响
ans[v(pos2)] -= sum;
else if(opt(pos2) == 3)//同上
ans[v(pos2)] += sum;
//至于其它的opt,证明它是修改,那么修改对它前面
tmp[tot] = A[pos2++];
}
}
for(int i = l ; i <= r ; ++i) A[i] = tmp[i];
}
int main() {
scanf("%d %d" , &n , &m);
for(int i = 1 , x ; i <= n ; ++i) {
scanf("%d" , &x);
insert(1 , i , x);
}
for(int i = 1 , opt , x , k ; i <= m ; ++i) {
scanf("%d %d %d" , &opt , &x , &k);
if(opt == 1) insert(1 , x , k);
else {
insert(2 , x - 1 , ++qry);
insert(3 , k , qry);
}
}
cdq(1 , cnt);
for(int i = 1 ; i <= qry ; ++i) printf("%d\n" , ans[i]);
return 0;
}
最后说一句,左闭右闭大法好!