hihocoder #1161 : 八卦的小冰

将所有的边定向,从度小的连向度大的,每一个点对于所有的入边,记录这个点性别相同和性别相异的亲和度和,对于所有的出边,用邻接表存边。。。。那么一个点的亲和度对答案的贡献就由入边的亲和度和和出边的亲和度和组成,出边的亲和度和暴力求。。。。那么3种操作就可以维护了。。。。

#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <math.h>
#include <time.h>
#define maxn 100005
#define maxm 200005
#define eps 1e-7
#define mod 1000000007
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R
#define pii pair<int, int>
#pragma comment(linker, "/STACK:16777216")
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
//head

struct node
{
	int op, x, y, z;
	node(int op = 0, int x = 0, int y = 0, int z = 0) : op(op), x(x), y(y), z(z) {}
}op[maxm];

map<int, int> mpp[maxn];
LL res[maxn][2];
int in[maxn];
int sex[maxn];
int n, m, m2;
LL ans;

void solve(int x, int flag)
{
	ans += res[x][sex[x] ^ 1] * flag;
	for(map<int, int>::iterator it = mpp[x].begin(); it != mpp[x].end(); it++) {
		if(sex[x] ^ sex[it->first]) ans += it->second * flag;
		res[it->first][sex[x]] += it->second * flag;
	}
}

void op1(int x)
{
	solve(x, -1);
	sex[x] ^= 1;
	solve(x, 1);
}

void op2(int x, int y, int z)
{
	if(in[x] > in[y] || in[x] == in[y] && x > y) swap(x, y);
	if(mpp[x].count(y)) {
		if(sex[x] ^ sex[y]) ans -= mpp[x][y];
		res[y][sex[x]] -= mpp[x][y];
	}
	mpp[x][y] = z;
	if(sex[x] ^ sex[y]) ans += z;
	res[y][sex[x]] += z;
}

void work()
{
	ans = 0;
	scanf("%d%d%d", &n, &m, &m2);
	for(int i = 1; i <= n; i++) scanf("%d", &sex[i]);
	for(int i = 1; i <= n; i++) mpp[i].clear(), in[i] = res[i][0] = res[i][1] = 0;
	
	int op_cnt = 0, x, y, z, k;
	for(int i = 0; i < m; i++) {
		scanf("%d%d%d", &x, &y, &z);
		in[x]++, in[y]++;
		op[op_cnt++] = node(2, x, y, z);
	}
	for(int i = 0; i < m2; i++) {
		scanf("%d", &k);
		if(k == 1) scanf("%d", &x);
		if(k == 2) scanf("%d%d%d", &x, &y, &z), in[x]++, in[y]++;
		op[op_cnt++] = node(k, x, y, z);
	}
	for(int i = 0; i < op_cnt; i++) {
		if(op[i].op == 1) op1(op[i].x);
		if(op[i].op == 2) op2(op[i].x, op[i].y, op[i].z);
		if(op[i].op == 3) printf("%lld\n", ans);
	}
}

int main()
{
	int _;
	scanf("%d", &_);
	for(int i = 1; i <= _; i++) {
		printf("Case #%d:\n", i);
		work();
	}
	
	
	return 0;
}


你可能感兴趣的:(hihocoer)