http://codeforces.com/contest/707/problem/E
题意:
给n*m矩阵,给k条链,链的每个节点有一个权值,每次查询一个子矩阵,求子矩阵之和
n,m,k都是2000以内,链的长度也是2000以内
每次操作 要么查询子矩阵,要么把一条链抹去,或恢复
由于链长只有2000,暴力模拟
对于查询矩阵和与单点更新就用二维树状数组咯
更新链的时候注意,每次直接更新链会T,要标记一下,在查询时统一更新才可以水过去。。正解看不懂、2333
1.6s/3S
//poj1195
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=1e-5;
int n,m;
const int maxn=2005;
struct tree
{
long long num[maxn][maxn];
inline int lowbit(int x)
{
return x&-x;
}
void add(int x,int y,long long a)
{
int i,j;
for (i=x; i<=n; i+=lowbit(i))
{
for (j=y; j<=m; j+=lowbit(j))
num[i][j]+=a;
}
}
long long query(int x,int y)
{
long long ans=0,i,j;
for (i=x; i>0; i-=lowbit(i))
{
for (j=y; j>0; j-=lowbit(j))
ans+=num[i][j];
}
return ans;
}
};
struct node
{
int x,y, w;
};
struct line
{
int len;
vector<node> p;
};
line llo[2005];
tree tp;
long long query(int l,int b,int r,int t)
{
long long ret=tp.query(r,t);
ret-=tp.query(l-1,t);
ret-=tp.query(r,b-1);
ret+=tp.query(l-1,b-1);
return ret;
}
int vis[2005];
int real[2005];
int main()
{
int k;
cin>>n>>m>>k;
for (int i=1; i<=k; i++)
{
scanf("%d",&llo[i].len);
node tmp;
for (int j=1; j<=llo[i].len; j++)
{
scanf("%d%d%d",&tmp.x,&tmp.y,&tmp.w);
llo[i].p.push_back(tmp);
tp.add(tmp.x,tmp.y,tmp.w);
}
}
int q;
cin>>q;
char op[10];
for (int i=1; i<=q; i++)
{
scanf("%s",op);
if(op[0]=='A')
{
int l,r,b,t;
for (int h=1; h<=k; h++)
{
if (real[h]==vis[h]) continue;
for (int j=0; j<llo[h].p.size(); j++)
{
int xx=llo[h].p[j].x;
int yy=llo[h].p[j].y;
int w=llo[h].p[j].w;
if (vis[h]==1) w=-w;
tp.add(xx,yy,w);
real[h]=vis[h];
}
}
scanf("%d%d%d%d",&l,&b,&r,&t);
long long ret=query(l,b,r,t);
printf("%lld\n",ret);
}
else
{
int x;
scanf("%d",&x);
vis[x]^=1;
}
}
return 0;
}