【BZOJ2120】数颜色 循环

本文探讨了如何通过离散化技巧解决一个看似简单的暴力算法问题,涉及树套树结构和复杂的数据操作。通过实例分析,揭示了离散化在处理大规模数据集时的重要性和必要性,同时解释了为何某些情况下常规的暴力方法可能无法有效解决问题。

树套树!Oh!God!No!

一个萌萌哒的同班同学(PoPoQQQ)告诉我,这题其实是水暴力!

(PS:这么水的题你为什么要刷?RE:因为下午偷偷玩游戏被老师发现结果假期被罚BZOJ十道题~~~况且我本来就是一只大水怪~~~)

令人费解的是,此题必须用到离散化才能过。

(PS:你逗我,10^6直接做就好了啦!RE:我tm也不知道为什么。可能是某个神奇的常数~~~)

附:数颜色 C++代码(未离散化,TLE):

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 10010
#define M 1000010
int n,m,a[N],mark[M],ans;
bool getopt()
{
	char ch;
	while(!isalpha(ch=getchar()));
	if(ch=='Q') return true;
	return false;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int x,y,i=1;i<=m;i++)
	{
		bool opt=getopt();
		scanf("%d%d",&x,&y);
		ans=0;
		if(opt)
		{
			for(int j=x;j<=y;j++)
				if(mark[a[j]]!=i)
					ans++,mark[a[j]]=i;
			printf("%d\n",ans);
		}
		else
			a[x]=y;
	}
}
数颜色 C++代码实现(2216MS ACCEPTED):

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 12010
#define M 1000010
int n,m,a[N],used[M],mark[N],ans,tot,now;
char ch[10];
int main()
{
	cin>>n>>m;
	for(int x,i=1;i<=n;i++)
	{
		scanf("%d",&x);
		if(!used[x])
			used[x]=++tot;
		a[i]=used[x];
	}
	for(int x,y,i=1;i<=m;i++)
	{
		scanf("%s%d%d",ch,&x,&y);
		if(ch[0]=='Q')
		{
			ans=0;++now;
			for(int j=x;j<=y;j++)
				if(mark[a[j]]!=now)
					ans++,mark[a[j]]=now;
			printf("%d\n",ans);
		}
		else
		{
			if(!used[y])
				used[y]=++tot;
			a[x]=used[y];
		}
	}
}


问题陈述 在AtCoder的国家有 $N$ 个动物园,编号为 $1$ 到 $N$ 。 $i$ 动物园门票为 $C_i$ 日元。 铃木先生喜欢 $M$ 种动物,动物 $1,\dots,M$ 。 $i$ 可以在 $K_i$ 动物园看到,即动物园 $A_{i,1},\dots,A_{i,K_i}$ 。 求所有动物每种至少看两次所需的最低总入场费。 如果你多次访问同一个动物园,那里的动物被认为每次访问一次。 # # #约束 —— $1 \le N \le 10$ —— $1 \le M \le 100$ —— $0 \le C_i \le 10^9$ —— $1 \le K_i \le N$ —— $1 \le A_{i,j} \le N$ —— $j \neq j' \Longrightarrow A_{i,j} \neq A_{i,j'}$ —所有输入值均为整。 # # #输入 输入来自标准输入,格式如下: $N$ $M$ $C_1$ $\dots$ $C_N$ $K_1$ $A_{1,1}$ $\dots$ $A_{1,K_1}$ $\vdots$ $K_M$ $A_{M,1}$ $\dots$ $A_{M,K_M}$ ###输入1 4 3 1000 300 700 200 3 1 3 4 3 1 2 4 2 1 3 ###输出示例 1800 例如,下面的时间表实现了看到 $1,2,3$ 动物至少两次,共计 $1800$ 日元: -去动物园 $3$ 。支付 $700$ 日元,看到动物 $1$ 和 $3$ 。 -去动物园 $3$ 。支付 $700$ 日元,看到 $1$ 和 $3$ 动物。 -去动物园 $4$ 。支付 $200$ 日元,可以看到 $1$ 和 $2$ 动物。 -去动物园 $4$ 。支付 $200$ 日元,看到动物 $1$ 和 $2$ 。 ###示例输入2 7 6 500 500 500 500 500 500 1000 3 1 2 7 3 2 3 7 3 3 4 7 3 4 5 7 3 5 6 7 3 6 1 7 ###示例输出2 2000 通过参观两次动物园 $7$ ,您可以看到 $1,2,3,4,5,6$ 每只动物两次,共计 $2000$ 日元。 写出这道题目的c++代码,并保证通过所有样例,运行时间在2s内,运行内存在256mb内
最新发布
05-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值