upc秋季组队训练第十七场(队列+区间筛)

问题 C: Unique Values

题目描述
Arup has to make many practice questions for his Computer Science 1 students. Since many of the questions deal with arrays, he has to generate arrays for his students. Since he doesn’t want to
give them difficult practice problems, he always guarantees that the arrays (given to the students) have unique values. Namely, no value will appear twice in any of his arrays.

Unfortunately, Arup is too lazy to generate arrays! About 20 years ago when he started teaching Computer Science 1, he made one really long array to reuse but this long array may have duplicate
values. When he makes problems, he simply grabs a contiguous subsequence of this long array to be the array to be used for a problem but he needs to make sure the contiguous subsequence does
not contain duplicates. If the long array has terms a[0], a[1], …, a[n-1], a contiguous subsequence of the long array is any sequence of j – i + 1 terms a[i], a[i+1], …, a[j] where 0 ≤ i ≤ j ≤ n – 1.

Given an array of n integers, determine how many contiguous subsequences of the array do not contain any repeated values. Note that two subsequences with the same contents are considered
different (i.e., both counted in the total) if they start at different locations of the original long array.
输入
The first input line contains a single positive integer, n (1 ≤ n ≤ 105 ), representing the size of the input array. The following line contains n space separated integers, representing the values of the
input array, in the order they appear in the array. Each of the array values will be an integer between 1 and 109 , inclusive.
输出
On a line by itself, output the total number of contiguous subsequences of the input array that do not contain any repeated values.
样例输入 Copy
【样例1】
5
1 1 2 1 5
【样例2】
8
2 12 3 12 3 2 6 9
样例输出 Copy
【样例1】
9
【样例2】
22

题意:
给你n个数字,问有多少个不存在相同元素的子序列
下面来看我队友的神操作
定义一个双端队列
每加入一个数字,就给标记这个数字的数组++
如果队列中存在这个数字,循环当前队列
如果这个元素的个数大于等于2,就说明当前子序列不符合题意,把队首元素出队,相应数量–
重复上述操作

ll n;
ll a[maxn];
deque<ll> q; 
map<ll,ll> vis;

int main(){
	
	scanf("%lld",&n);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	
	ll ans = 0;
	for(int i=1;i<=n;i++){
		if(vis[a[i]] == 0){ // 说明这个数没有出现过 
			q.push_back(a[i]); // 入队列
			vis[a[i]]++; 
		}else{ // 队列中存在 
			q.push_back(a[i]); // 再次加入队列 
			vis[a[i]]++;
			while(q.size() && vis[a[i]] >= 2){ // 说明这个数重复了 
				vis[q.front()]--; // 队首元素出队
				q.pop_front(); 
			}
		}
		ans += q.size();
	}
	printf("%lld\n",ans);
	return 0;
}

问题 E: Sum of a Function

题目描述
Everyone knows that Arup loves prime numbers! This is why he teaches the cryptography course at UCF. Recently, Arup defined the following function on positive integers, n, greater than 1:

f(n) = the smallest prime factor of n

For example, f(14) = 2, f(15) = 3, f(16) = 2 and f(17) = 17.

Using this function, we can generate a sequence of terms f(s), f(s+1), f(s +2), …, f( e), where s designates the starting function input and e designates the ending function input.

Arup thinks these sequences are interesting, but what he’s really curious about is finding the sum of the k minimum elements in one of these sequences. Can you write a program to help him?

Given s, e, and k, find the sum of the k minimum values in the sequence f(s), f(s+1), f(s +2), …, f(e).
输入
The first and only input line will contain three positive integers, s (2 ≤ s ≤ 1018 ), e (s +100 ≤ e ≤ s+106 ), and k (1 ≤ k ≤ 0.9 * (e – s + 1)), representing (respectively) the starting function input, the ending function input, and the number of minimum terms to sum.
输出
On a line by itself, print the sum of the k minimum terms of the designated sequence.
样例输入 Copy
【样例1】
100 200 70
【样例2】
213 419 169
样例输出 Copy
【样例1】
165
【样例2】
546
提示
Even though the input specification does not allow “14 17 3” as an input case (i.e., this case will not be in the judge data), it is a simple case that you may want to use for testing purposes – the output (7) can be verified easily on paper. (BTW, the intended solution should solve this case properly anyway.)

题意:
这大概是个区间筛的裸题?大概…
题目大概意思是说给你一个区间
求区间内前k个素数的和
乍一看数据范围很大但是区间范围只有1e6
这种题就可以用区间筛了
我也是第一次学区间筛,就当存板子了

const int N = 5000010;
int cnt; 
int f[N]; // 存储区间l+j的最小质因子 
int prime[N]; // 存储1到1e6的素数 
bool vis[N]; // 标记1到1e6的数 
bool dabiao[N]; // 标记区间内的数 
void get_prime(){ // 先筛1到1e6的数 
 
 	for(int i=2;i<N;i++){
		if(vis[i] == 0) prime[cnt++] = i,f[i] = i;
		for(int j=0;prime[j]*i<N;j++){
			if(f[prime[j]*i] == 0) f[prime[j]*i] = prime[j];
			vis[i*prime[j]] = true;
			if(i%prime[j] == 0) break;
		}
	}
}

void qujianshai(ll l,ll r){ 

	memset(f,0,sizeof f);
	for(ll i=0;i < cnt&&prime[i]*prime[i]<=r;i++){
		for(ll j=max(2LL,(l+prime[i]-1)/prime[i])*prime[i];j<=r;j+=prime[i]){
			// 1到1e6中的数字映射到区间中 
			if(j >= l){
				dabiao[j-l] = 1; // 表示为合数 
				if(!f[j-l]) f[j-l] = prime[i];
			}
		}
	}
}

ll st[N],t;
int main(){
	
	get_prime();
	ll s,e,k;
	s = read, e = read, k = read; 
	f[1] = 1;
	if(s >= N || e >= N){
		qujianshai(s,e);
		for(int i=0;i<=e-s;i++){ // 需要区间筛 
			if(dabiao[i] == 0){ // 说明是区间内的素数 
				st[++t] = i+s;
			}else{
				st[++t] = f[i];
			}
		}
		sort(st+1,st+t+1);
		ll ans = 0;
		for(ll i=1;i<=k;i++){
			ans += st[i];
		}
		cout << ans << endl;
	}else{
		for(int i=s;i<=e;i++){
			st[++t] = f[i];
		} 
		sort(st+1,st+t+1);
		ll ans = 0;
		for(ll i=1;i<=k;i++){
			ans += st[i];
		}
		cout << ans << endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你数过天上的星星吗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值