2020年1月23日山师训练赛2

题目链接

C - 【The__Flash】的电影

题意:有 n 个人,每个人会且仅会一种语言.
有 m 个电影,电影语言分为 音频语言 和 字幕语言,且同场电影的音频语言和字幕语言不同.
当人观看电影时,如果他会该电影的音频语言,他会非常高兴.
当人观看电影时,如果他会该电影的字幕语言,他会比较高兴.
现要求选择一场电影,使得非常高兴的人数最多,若解不唯一,则选择比较高兴人数最多,输出该电影的编号.
对于:给出的数据:(1 ≤ n ≤ 200 000)(1 ≤ m ≤ 200 000) 每个人掌握的语言(1 ≤ ai ≤ 109) 对应电影的音频语言
(1 ≤ bj ≤ 109) 对应电影的字母语言 (1 ≤cj ≤ 109)

解法:如果直接写的话发现编译会出错,原因是 ai, bi, ci 的数据范围太大,数组开不下,我们的目的只是根据大小对ai,bi,ci来排序,只需要他们的相对大小,据此来重新编号,需要用到一个方法离散化,离散化的步骤如下:

  1. 将数据写到一个数组 d 中
  2. 将数组 d 进行排序(sort())
  3. 排序后对数组 d 进行去重(unique())
    当询问元素的相对大小时,由于数据有序,我们可以采用二分查找的方式查询元素 x 的位置.

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
const int maxn=2e5+10; 
typedef long long ll;
ll a[maxn],b[maxn],c[maxn],d[3*maxn+10],num[maxn],len,n,m;
using namespace std; 
 
void f()
{    len=0;
	for(int i=1;i<=m;i++)
	  d[++len]=a[i];
	  	for(int i=1;i<=m;i++)
	  d[++len]=b[i];
	  	for(int i=1;i<=m;i++)
	  d[++len]=c[i];
	  sort(d+1,d+len+1);
	  len=unique(d+1,d+len+1)-d-1;//这里减去d+1之后记录的是d数组对应的 
	  
}


int w(int x)//二分查找x在d中的位置 
{
	return lower_bound(d+1,d+len+1,x)-d;
}



int main()
{

scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
scanf("%d", &m);
for(int i = 1; i <= m; ++i) scanf("%d", &b[i]);
for(int i = 1; i <= m; ++i) scanf("%d", &c[i]);
f();
for(int i=1;i<=n;i++)
  num[w(a[i])]++;
  ll num1_max=0,num2_max=0,num1,num2,ans=1;
  for(int i=1;i<=m;i++)
  {
  	num1=num[w(b[i])];
	  num2=num[w(c[i])];
	  if(num1>num1_max||num1==num1_max&&num2>num2_max)
	  {
	  	num1_max=num1;
	  	num2_max=num2;
	  	ans=i;
	  }
  }
  cout<<ans<<endl;
}

J - 【The__Flash】的球球

题意:中文题,描述见原题链接

解法:若是每涂一次就循环一次,太复杂会超时,所以需要用到差分数组(前缀和的逆运算),为此我看了一下大佬的差分数组讲解,数数组a[i]即为所求气球涂颜色的次数,那么我们就用差分数组的方法去求,假如现在对数列中区间[L,R]上的数加上x,第一个受影响的差分数组中的元素为a[L],即令a[L]+=x,那么后面数列元素在计算过程中都会加上x;最后一个受影响的差分数组中的元素为a[R],所以令a[R+1]-=x,即可保证不会影响到R以后数列元素的计算。这样我们不必对区间内每一个数进行处理,只需处理两个差分后的数即可.;

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100010;
int main()
{
	int n,a[maxn]={0},k;
	while(scanf("%d",&n)!=0)
	{ memset(a,0,sizeof(a));
	k=n;
    while(n--)
    {
    	int l,r;
    	cin>>l>>r;
    	a[l]++;
    	a[r+1]--;
    	
	}
	for(int i=2;i<=k;i++)
	{
		a[i]+=a[i-1];
	}
	for(int i=1;i<=k;i++)
	
	cout<<a[i]<<' ';
    cout<<endl;
}
	
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值