是的真相就是耍流氓暴力!!!
离线处理
处理出每个点的点度deg[i](无重边)
维护一个数组from_small[i],表示与i相邻的点中点度比deg[i]小的点的在线数量
然后对于每个询问,暴力数出i的相邻点中点度比deg[i]大的点在线的数量,然后加上from_small[i],就是答案
复杂度是O(操作数*sqrt(点度之和))
证明:
每次询问的复杂度为O(1) + O(遍历度数比deg[i]大的邻点)
设度数比deg[i]大的邻点有x个
此时有deg[i] >= x
所以i和他的邻点度数和至少为x*(x+1),
因为 sigma(deg[i]) <= 2*E (E为不重叠的边数)
所以满足deg[j] >= deg[i]的邻点的个数最多为sqrt(2*E)
证毕
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
#define snuke(it,x) for (__typeof((x).begin()) it = (x).begin(); it != (x).end(); it ++)
typedef pair<int,int> PII;
const int N = 55555;
const int Q = 255555;
const int M = 401000;
char op[Q];
int qa[Q],qb[Q],ua[M],ub[M];
int from_small[N],n,m,nq,deg[N],on,first_on[N],edge_state[M],dot_state[N];
vector<PII> edge;
vector<PII> G[N];
int get_edge_id(PII z) {
if (z.first>z.second) swap(z.first,z.second);
return lower_bound(edge.begin(),edge.end(),z)-edge.begin();
}
void modify_dot(int u,int st) {
dot_state[u] = st;
int dt = st==1 ? 1 : -1;
snuke(it,G[u]) {
int v = it->first;
int id = it->second;
if (!edge_state[id]) continue;
from_small[v] += dt;
}
}
void modify_edge(int u,int v,int st) {
int id = get_edge_id(PII(u,v));
edge_state[id] = st;
if (deg[u]>deg[v]) swap(u,v);
if (dot_state[u]==1) {
from_small[v] += st==1 ? 1 : -1;
}
}
int query_dot(int u) {
int ret = from_small[u];
snuke(it,G[u]) {
int v = it->first;
int id = it->second;
if (edge_state[id]==0) continue;
ret += dot_state[v];
}
return ret;
}
void work() {
sort(edge.begin(),edge.end());
edge.erase(unique(edge.begin(),edge.end()),edge.end());
int sz = (int)edge.size();
for (int i = 0; i < sz; i ++) {
deg[edge[i].first] ++;
deg[edge[i].second] ++;
}
for (int i = 0; i < sz; i ++) {
int u = edge[i].first;
int v = edge[i].second;
if (deg[u]>deg[v]) swap(u,v);
G[u].push_back(PII(v,i));
}
for (int i = 0; i < m; i ++) {
int id = get_edge_id(PII(ua[i],ub[i]));
edge_state[id] = 1;
}
for (int i = 0; i < on; i ++) {
modify_dot(first_on[i],1);
}
for (int i = 0; i < nq; i ++) {
int u = qa[i];
int v = qb[i];
if (op[i]==‘O‘) {
modify_dot(u,1);
} else if (op[i]==‘F‘) {
modify_dot(u,0);
} else if (op[i]==‘A‘) {
modify_edge(u,v,1);
} else if (op[i]==‘D‘) {
modify_edge(u,v,0);
} else {
printf("%d\n",query_dot(u));
}
}
}
int main() {
scanf("%d%d%d",&n,&m,&nq);
scanf("%d",&on);
for (int i =0 ; i < on; i ++) {
scanf("%d",&first_on[i]); first_on[i] --;
}
for (int i = 0; i < m; i ++) {
scanf("%d%d",&ua[i],&ub[i]); ua[i] --; ub[i] --;
if (ua[i]>ub[i]) swap(ua[i],ub[i]);
edge.push_back(PII(ua[i],ub[i]));
}
for (int i = 0; i < nq; i ++) {
char s[3];
scanf("%s",s);
op[i] = s[0];
if (op[i]==‘A‘ || op[i]==‘D‘) {
scanf("%d%d",&qa[i],&qb[i]); qa[i] --; qb[i] --;
if (qa[i]>qb[i]) swap(qa[i],qb[i]);
edge.push_back(PII(qa[i],qb[i]));
} else {
scanf("%d",&qa[i]); qa[i] --;
}
}
work();
return 0;
}
Codeforces398D Instant Messanger,布布扣,bubuko.com
Codeforces398D Instant Messanger
原文:http://blog.csdn.net/hei_nero/article/details/21486703