啊最近准备初赛,这星期再进机房一步,直播吃屎
CDQ分治,就是对询问和修改离线后分治解答
这道题就是一道很简单的CDQ分治,大概思路就是下面这段代码
inline void solve (int l,int r) {
if ( l == r ) return ;
solve(l,mid);
solve(mid+1,r);
merge(l,r);
}
做法:
1、将一个询问拆分成四个询问,把询问和修改一起CDQ分治
2、递归完成后将左侧的修改和右侧的询问按照y为关键词排序,依次加入树状数组。
Tips:题目描述有点小问题,翻译过来应该是所有的点初值都是0,但这并不影响答案
#include <cassert>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define N 3000050
using namespace std;
typedef int LL;
struct Monster{ int x,y,s,mk,rank;LL ans; }Q[N];
bool cmp1(Monster p1,Monster p2 ){ return p1.y < p2.y; }
bool cmp2(Monster p1,Monster p2) { return p1.rank < p2.rank; }
int w,n,cmd;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int lowbit(int x) { return (x & (-x)); }
struct Small_Segment_Tree{
LL tr[N]; vector<int> tmp;
inline void add(int x,LL v) {
for (int i=x;i<=w;i+=lowbit(i)) {
tr[i] += v ;
tmp.push_back(i);
}
}
inline LL ask(int x) {
LL sum = 0;
for (int i=x;i>=1;i-=lowbit(i)) sum += tr[i];
return sum;
}
inline void clear() {
for (int i=0;i<tmp.size();i++) tr[ tmp[i] ] = 0;
tmp.clear();
}
}T;
inline void init(int &cmd) {
if (cmd == 1) {
Q[++n].x = read(), Q[n].y = read();
Q[n].s = read();
Q[n].mk = 1;
} else {
int x1 = read()-1 , y1 = read()-1 , x2 = read() , y2 = read();
Q[++n].x = x1 , Q[n].y = y1; Q[n].mk = 2;
Q[++n].x = x1 , Q[n].y = y2;
Q[++n].x = x2 , Q[n].y = y1;
Q[++n].x = x2 , Q[n].y = y2;
}
return ;
}
inline void merge(int l,int r,int mid) {
//memset(T.tr,0,sizeof(T.tr));
sort(Q+l,Q+mid+1,cmp1);
sort(Q+mid+1,Q+r+1,cmp1);
T.clear();
int i = l;
for (int j=mid+1;j<=r;j++) if (Q[j].mk != 1) {
while (i<=mid && Q[i].y <= Q[j].y) {
if (Q[i].mk == 1) T.add(Q[i].x , Q[i].s);
i++;
}
Q[j].ans += T.ask(Q[j].x);
}
}
void solve(int l,int r) {
if (l == r) return ;
int mid = (l + r) >> 1;
solve(l,mid);
solve(mid+1,r);
merge(l,r,mid);
}
int main()
{
read(); w = read();
while (( cmd = read() ) != 3) init(cmd);
for (int i=1;i<=n;i++) Q[i].rank = i;
solve(1,n);
sort(Q+1,Q+n+1,cmp2);
for (int i=1;i<=n;i++) if (Q[i].mk == 2) {
LL ans = Q[i+3].ans - Q[i+2].ans - Q[i+1].ans + Q[i].ans;
printf("%d\n",ans);
}
//debug();
return 0;
}