您的位置:首页 > 其它

cogs 1752. [BOI2007]摩基亚Mokia

2017-07-05 19:49 344 查看
题目链接:http://www.cogs.pro/cogs/problem/problem.php?pid=1752

cdq分治模版题。就是处理前缀和的时候这里变成了矩阵前缀和。我们采用扫描线的方法,用树状数组来维护一个矩阵的前缀和。

然后对于一个询问,我们采用矩阵前缀和的形式来处理这个询问,转化为4个操作。也就是对4个矩阵的处理。

然后看代码就可以了。

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 2e5+7;
typedef long long LL;
int n;
struct node
{
int x,y;
int qid;
int val;
int type;
node(){};
node(int X,int Y,int Val,int Type,int Qid = 0)
{
x = X;
y = Y;
val = Val;
type = Type;
qid = Qid;
}
bool operator <= (const node &a)const
{
return x == a.x?type < a.type : x < a.x;
}
} p[MAXN],temp[MAXN];
LL ans[10005];

LL val[MAXN*10];
void add(int x,int y)
{
for(; x <= n; x += x&-x)val[x] += y;
}
LL sum(int x)
{
LL ans = 0;
for(; x; x -= x&-x)ans += val[x];
return ans;
}

void cdq(int l,int r)
{
if(l == r)return;
int mid = (l+r)>>1;
cdq(l,mid);
cdq(mid+1,r);
int i = l, j = mid + 1;
int cnt = 0;
while(i <= mid && j <= r)
{
if(p[i] <= p[j])
{
if(p[i].type == 1)add(p[i].y,p[i].val);
temp[cnt++] = p[i++];
}
else
{
if(p[j].type == 2)ans[p[j].qid] += p[j].val*sum(p[j].y);
temp[cnt++] = p[j++];
}
}
while(j <= r)
{
if(p[j].type == 2)ans[p[j].qid] += p[j].val*sum(p[j].y);
temp[cnt++] = p[j++];
}
for(int ii = l ; ii < i ; ++ii)if(p[ii].type == 1)add(p[ii].y,-p[ii].val);//把树状数组清0,供下一次使用。
while(i <= mid)temp[cnt++] = p[i++];
for(int i = 0 ; i < cnt ; ++i)p[l++] = temp[i];
}

int main()
{
freopen("mokia.in","r",stdin);
freopen("mokia.out","w",stdout);
scanf("%*d%d",&n);
int x,y,t,c,x1,y1;
int id = 0 , qid = 0;
while(~scanf("%d",&t) && t!=3)
{
if(t == 1)
{
scanf("%d%d%d",&x,&y,&c);
p[++id] = node(x,y,c,1);
}
else
{
scanf("%d%d%d%d",&x,&y,&x1,&y1);
p[++id] = node(x-1,y-1,1,2,qid);
p[++id] = node(x1,y-1,-1,2,qid);
p[++id] = node(x-1,y1,-1,2,qid);
p[++id] = node(x1,y1,1,2,qid++);
}
}
cdq(1,id);
for(int i = 0 ; i < qid ; ++i)printf("%lld\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cdq分治