2019ccpc哈尔滨 E - Exchanging Gifts Gym 线性求解+unorderdmap

题目链接

Problem - E - Codeforces

题目大意

有两种操作 第一种是列出一个序列 第二种是合并之前出现的序列生成一个新的序列

问你最后序列的快乐值是多少

快乐值定义是 将序列随意排序后最大的与之前位置不同的元素个数

题目思路

经过观察发现

最大快乐值

数量最多的元素数量=maxv

总元素数量=tot

当maxv

否则快乐值 =tot-(maxv-(tot-maxv))

列出如下之图可看得更明白

有上图到下图 明显不快乐值为 最大的数量5 -剩余数量4=1

快乐值=9-1=8

问题是如何找到各个元素数量

由于每个操作2可以吸收两个序列

可以很容易想到拓补

但是该题有一个条件就是2操作的对象序号小于 i

那么该题就不需要拓扑了 直接从n到1线性求解

设置num【n】=1

若该点是操作2则将操作对象的num+=num【i】

若该点是操作1则该点包含所有的点的数量+=num【i】

若某一个点num【i】==0 就跳过

这样的时间复杂度是O(N+K)

但由于读入数量级的问题 很容易T

因此我用了一个超级快读(注意该快读无法读入其他类型)

static char buf[100000],*pa=buf,*pd=buf;
#define gc pa==pd&&(pd=(pa=buf)+fread(buf,1,100000,stdin),pa==pd)?EOF:*pa++
inline int read()
{
    register int x(0);register char c(gc);
    while(c<'0'||c>'9')c=gc;
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=gc;
    return x;
}

题目代码

#include
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
int t,n,m,T,q,x,y;

int lef[maxn],inlj[maxn];
ll num[maxn];
ll tot,maxv;
unordered_mapmp;
static char buf[100000],*pa=buf,*pd=buf;
#define gc pa==pd&&(pd=(pa=buf)+fread(buf,1,100000,stdin),pa==pd)?EOF:*pa++
inline int read()
{
    register int x(0);register char c(gc);
    while(c<'0'||c>'9')c=gc;
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=gc;
    return x;
}
//void dfs(int floor)
//{
//	if(lef[floor])
//	for(int i=0;iv[maxn];
int main()
{
	T=read();
	while(T--)
	{
		n=read();
		mp.clear();
		tot=maxv=0;
		
		for(int i=1;i<=n;i++)
		{
			t=read();
			v[i].clear();
			lef[i]=num[i]=0;
			if(t==1)
			{
				q=read();
				for(int j=0;j=1;i--)
			{
				if(num[i]==0)continue;
				int floor=i;
				if(lef[floor]==1)
				{
					num[v[floor][0]]+=num[i];
					num[v[floor][1]]+=num[i];
				}
				else 
				{
					for(int j=0;j

你可能感兴趣的:(算法,快读,CCPC)