Garlands CodeForces - 707E (离线树状数组)

大意: 给定n*m矩阵, k条链, 链上每个点有权值, 每次操作可以关闭或打开一条链或询问一个子矩阵内未关闭的权值和.

关键询问操作比较少, 可以枚举每条链, 暴力算出该条链对每个询问的贡献. 最后再按询问顺序切换链的状态, 只记录打开的链的贡献即可.

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#include <bitset>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, INF = 0x3f3f3f3f;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
//head




const int N = 2e3+20, M = 1e6+10;
int n, m, k, q, cnt;
int len[N], x[N][N], y[N][N], w[N][N], vis[N];
char op[M][10];
int t[M], t1[N], t2[N], t3[N], t4[N];
ll c[N][N], ans[N][N];
void upd(int x, int y, int w) {
	for (int i=x; i<=n+1; i+=i&-i) for (int j=y; j<=m+1; j+=j&-j) c[i][j]+=w;
}
ll qry(int x, int y) {
	ll r = 0;
	for (int i=x; i; i^=i&-i) for (int j=y; j; j^=j&-j) r+=c[i][j];
	return r;
}

int main() {
	scanf("%d%d%d", &n, &m, &k);
	REP(i,1,k) {
		scanf("%d", len+i);
		REP(j,1,len[i]) { 
			scanf("%d%d%d",&x[i][j],&y[i][j],&w[i][j]);
			++x[i][j], ++y[i][j];
		}
	}
	scanf("%d", &q);
	REP(i,1,q) {
		scanf("%s", op[i]);
		if (op[i][0]=='S') scanf("%d",t+i);
		else { 
			++cnt;
			scanf("%d%d%d%d",t1+cnt,t2+cnt,t3+cnt,t4+cnt);
			++t1[cnt],++t2[cnt],++t3[cnt],++t4[cnt];
		}
	}
	REP(i,1,k) {
		REP(j,1,len[i]) upd(x[i][j],y[i][j],w[i][j]);
		REP(j,1,cnt) {
			int x1=t1[j],y1=t2[j],x2=t3[j],y2=t4[j];
			ans[i][j] = qry(x2,y2)-qry(x2,y1-1)-qry(x1-1,y2)+qry(x1-1,y1-1);
		}
		REP(j,1,len[i]) upd(x[i][j],y[i][j],-w[i][j]);
	}
	int now = 0;
	REP(i,1,q) {
		if (op[i][0]=='S') vis[t[i]] ^= 1;
		else {
			++now;
			ll r = 0;
			REP(i,1,k) if (!vis[i]) r+=ans[i][now];
			printf("%lld\n", r);
		}
	}
}

猜你喜欢

转载自www.cnblogs.com/uid001/p/10583340.html
今日推荐