卧薪尝胆,厚积薄发。
SHOI2013 发微博
Date: Mon Sep 17 14:28:00 CST 2018 In Category: NoCategory

Description:

$n$ 个人, $m$ 个操作,每次操作为 $a$ 发了一条微博, $a$ 和 $b$ 成为好友, $a$ 和 $b$ 解除好友,直接好友可以看见对方的微博,问最后每个人看见了多少别人的微博。
$1\le n\le 200000$

Solution:

发现并不能用什么数据结构来维护, $LCT$ 也不能修改整棵树信息,一种解法是每个人用一个 $set<pair<int,int>>$ 来维护所有和他是好友的人, $pair$ 的第一个元素是好友的编号,第二个元素是建立好友时 $a$ 发的微博个数,在解除好友时用这时 $a$ 发的微博个数减去建立时的就是这段时间对答案的贡献,最后再把到最后都是好友的统计一遍。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<set>
#include<cstring>
using namespace std;
inline char getc()
{
register char c = getchar();
while(c != '!' && c != '+' && c != '-')c = getchar();
return c;
}
inline int read()
{
register int res = 0;
register char c = getchar();
while(!isdigit(c))c = getchar();
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res;
}
int n,m;
#define MAXN 200010
set< pair<int,int> > s[MAXN];
int cnt[MAXN];
int ans[MAXN];
int main()
{
scanf("%d%d",&n,&m);
char c;
int a,b;
for(int i = 1;i <= m;++i)
{
c = getc();
if(c == '!')
{
a = read();
++cnt[a];
}
if(c == '+')
{
a = read();b = read();
s[a].insert(make_pair(b,cnt[a]));
s[b].insert(make_pair(a,cnt[b]));
}
if(c == '-')
{
a = read();b = read();
set< pair<int,int> >::iterator it;
it = s[a].lower_bound(make_pair(b,0));
ans[b] += cnt[a] - it -> second;
s[a].erase(it);
it = s[b].lower_bound(make_pair(a,0));
ans[a] += cnt[b] - it -> second;
s[b].erase(it);
}
}
for(int i = 1;i <= n;++i)
{
for(set< pair<int,int> >::iterator it = s[i].begin();it != s[i].end();++it)
{
ans[it -> first] += cnt[i] - it -> second;
}
}
for(int i = 1;i <= n;++i)
{
cout << ans[i] << " ";
}
cout << endl;
return 0;
}
In tag:
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡