[VK Cup 2016 - Round 3] - D Bearish Fanpages

洛谷传送门

Codeforces传送门

题目描述

There is a social website with nnn fanpages, numbered 111 through nnn . There are also nnn companies, and the iii-th company owns the iii -th fanpage.

Recently, the website created a feature called following. Each fanpage must choose exactly one other fanpage to follow.

The website doesn’t allow a situation where iii follows jjj and at the same time jjj follows iii . Also, a fanpage can’t follow itself.

Let’s say that fanpage iii follows some other fanpage j0j_{0}j0​ . Also, let’s say that iii is followed by kkk other fanpages j1,j2,...,jkj_{1},j_{2},...,j_{k}j1​,j2​,...,jk​ . Then, when people visit fanpage iii they see ads from k+2k+2k+2 distinct companies: i,j0,j1,...,jki,j_{0},j_{1},...,j_{k}i,j0​,j1​,...,jk​ . Exactly tit_{i}ti​ people subscribe (like) the iii -th fanpage, and each of them will click exactly one add. For each of k+1k+1k+1 companies j0,j1,...,jkj_{0},j_{1},...,j_{k}j0​,j1​,...,jk​, exactly [VK Cup 2016 - Round 3] - D Bearish Fanpages people will click their ad. Remaining [VK Cup 2016 - Round 3] - D Bearish Fanpages people will click an ad from company ii (the owner of the fanpage).

The total income of the company is equal to the number of people who click ads from this copmany.

Limak and Radewoosh ask you for help. Initially, fanpage iii follows fanpage fif_{i}fi​ . Your task is to handle qqq queries of three types:

  • 1 i j — fanpage iii follows fanpage jjj from now. It’s guaranteed that iii didn’t follow jjj just before the query. Note an extra constraint for the number of queries of this type (below, in the Input section).
  • 2 i — print the total income of the iii -th company.
  • 3 — print two integers: the smallest income of one company and the biggest income of one company.

输入输出格式

输入格式:

The first line of the input contains two integers nnn and qqq (3n100000,1q100000)( 3\le n\le 100000 , 1\le q\le 100000 )(3≤n≤100000,1≤q≤100000) — the number of fanpages and the number of queries, respectively.

The second line contains nnn integers t1,t2,...,tnt_{1},t_{2},...,t_{n}t1​,t2​,...,tn​ (1ti1012)( 1\le t_{i}\le10^{12} )(1≤ti​≤1012) where tit_{i}ti​ denotes the number of people subscribing the iii -th fanpage.

The third line contains nnn integers f1,f2,...,fn(1fin)f_{1},f_{2},...,f_{n} ( 1\le f_{i}\le n )f1​,f2​,...,fn​(1≤fi​≤n). Initially, fanpage iii follows fanpage fif_{i}fi​ .

Then, qqq lines follow. The iii -th of them describes the iii -th query. The first number in the line is an integer $type_{i} ( 1\le type_{i}\le 3 ) $— the type of the query.

There will be at most 500005000050000 queries of the first type. There will be at least one query of the second or the third type (so, the output won’t be empty).

It’s guaranteed that at each moment a fanpage doesn’t follow itself, and that no two fanpages follow each other.

输出格式:

For each query of the second type print one integer in a separate line - the total income of the given company. For each query of the third type print two integers in a separate line - the minimum and the maximum total income, respectively.

输入输出样例

输入样例#1:

5 12
10 20 30 40 50
2 3 4 5 2
2 1
2 2
2 3
2 4
2 5
1 4 2
2 1
2 2
2 3
2 4
2 5
3

输出样例#1:

10
36
28
40
36
9
57
27
28
29
9 57

解题分析

一开始以为是什么牛逼的数据结构, 结果是个大暴力。

考虑对于每个点只维护其子节点和自己对自己的答案贡献为ans[i]ans[i]ans[i], 然后某个节点的答案就是父节点对自己的贡献加上维护的自己的这个值, 用个setsetset就可以从小到大按照ans[i]ans[i]ans[i]排序儿子节点了。 然后在外面用一个multisetmultisetmultiset存所有节点的子节点加上这个节点对它们的贡献的最大最小值(即真正的答案)。

然后修改的时候只会有xxx, f[x]f[x]f[x],f[f[x]]f[f[x]]f[f[x]], yyy, f[y]f[y]f[y]的答案值可能改变, 单独拉出来它们及其父亲修改再塞回去就好了。

至于单独的一个查询, 直接输出ans[i]ans[i]ans[i]和f[i]f[i]f[i]对iii的贡献。

代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <set>
#include <vector>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define MX 100500
#define gc getchar()
#define ll long long
template <class T>
IN void in(T &x)
{
	x = 0; R char c = gc;
	for (; !isdigit(c); c = gc);
	for (;  isdigit(c); c = gc)
	x = (x << 1) + (x << 3) + c - 48;
}
template <class T> IN T max(T a, T b) {return a > b ? a : b;}
template <class T> IN T min(T a, T b) {return a < b ? a : b;}
ll ans[MX], val[MX];
int n, q;
std::multiset <ll> Ans;
struct Comp
{
	IN bool operator () (const int &x, const int &y)
	{return ans[x] == ans[y] ? x < y : ans[x] < ans[y];}
};
struct Node
{
	std::set <int , Comp> st;
	int deg, fat;
	IN std::vector <int> get()//max and min
	{
		std::vector <int> ret;
		if (!st.empty())
		ret.push_back(*st.begin());
		if (st.size() > 1)
		{
			auto i = st.end(); i--;
			ret.push_back(*i);
		}
		return ret;
	}
}dat[MX];
IN ll other(R int x) {return val[x] / (dat[x].deg + 2);}//contribution to other points
IN ll self(R int x) {return val[x] - (dat[x].deg + 1) * other(x);}
int main(void)
{
	int typ, foo, bar;
	in(n), in(q);
	std::vector <int> res;
	for (R int i = 1; i <= n; ++i) in(val[i]);
	for (R int i = 1; i <= n; ++i)
	{
		in(dat[i].fat);
		++dat[dat[i].fat].deg;
		dat[dat[i].fat].st.insert(i);
	}
	for (R int i = 1; i <= n; ++i)
	{
		dat[dat[i].fat].st.erase(i);
		ans[i] = self(i);
		for (auto j : dat[i].st) ans[i] += other(j);
		dat[dat[i].fat].st.insert(i);
	}
	for (R int i = 1; i <= n; ++i)
	{
		res = dat[i].get();
		for (auto j : res) Ans.insert(other(i) + ans[j]);
	}
	W (q--)
	{
		in(typ);
		if (typ == 1)
		{
			in(foo), in(bar);
			std::set <int> base = {foo, dat[foo].fat, dat[dat[foo].fat].fat, bar, dat[bar].fat};
			std::set <int> upd = base;
			for (auto i : base) upd.insert(dat[i].fat);
			for (auto i : upd)
			{
				res = dat[i].get();
				for (auto j : res) Ans.erase(Ans.find(other(i) + ans[j]));
			}
			for (auto i : base) dat[dat[i].fat].st.erase(i);
			for (R int tp = -1; tp <= 1; tp += 2)
			{
				for (auto i : base)
				{
					ans[i] += tp * self(i);
					for (auto j : base) if (i == dat[j].fat)
					ans[i] += tp * other(j);
				}
				if (tp == -1)
				--dat[dat[foo].fat].deg, ++dat[bar].deg, dat[foo].fat = bar;
			}
			for (auto i : base) dat[dat[i].fat].st.insert(i);
			for (auto i : upd)
			{
				res = dat[i].get();
				for (auto j : res) Ans.insert(ans[j] + other(i));
			}
		}
		else if (typ == 2) in(foo), printf("%I64d\n", ans[foo] + other(dat[foo].fat));
		else
		{
			printf("%I64d ", *Ans.begin());
			auto i = Ans.end(); i--;
			printf("%I64d\n", *i);
		}
	}
}
上一篇:二分(HDU2289 Cup)


下一篇:VK Cup 2012 Round 1 D. Distance in Tree (树形dp)