zoukankan      html  css  js  c++  java
  • CFEducational Codeforces Round 66题解报告

    CFEducational Codeforces Round 66题解报告

    感觉丧失了唯一一次能在CF上超过wqy的机会QAQ

    A

    不管

    B

    不能直接累计乘法打(tag),要直接跳

    C

    考虑二分第(k)小的值

    那么问题就变成了

    每一个数变成了([x-mid,x+mid])的一段区间,如果有一个位置被覆盖了超过(k)

    那么(mid)一定合法

    类似括号匹配

    每次碰到左端点就贡献+1

    右端点就统计答案然后-1

    维护答案的同时顺便维护位置就好了

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    #include<vector>
    #include<ctime>
    #include<cmath>
    #define LL long long
    #define pii pair<int,int>
    #define mk make_pair
    #define fi first
    #define se second
    using namespace std;
    const int N = 4e5 + 3;
    int a[N];
    int n,k,ans;
    vector <pii> G;
    inline int read(){
    	int v = 0,c = 1;char ch = getchar();
    	while(!isdigit(ch)){
    		if(ch == '-') c = -1;
    		ch = getchar();
    	}
    	while(isdigit(ch)){
    		v = v * 10 + ch - 48;
    		ch = getchar();
    	}
    	return v * c;
    }
    inline bool check(int mid){
    	G.clear();
    	for(int i = 1;i <= n;++i) G.push_back(mk(a[i] - mid,0)),G.push_back(mk(a[i] + mid,1));
    	sort(G.begin(),G.end());
    	int now = 0;
    	for(int i = 0;i < (int)G.size();++i){
    		if(G[i].se == 0) now++;
    		else{
    			if(now >= k){ans = G[i].fi;return 1;}
    			now--;	
    		}
    	}
    	return 0;
    }
    int main(){
    	int T = read();
    	while(T--){
    		n = read(),k = read() + 1;
    		for(int i = 1;i <= n;++i) a[i] = read();
    		int l = 0,r = 1e9;
    		while(l <= r){
    			int mid = (l + r) >> 1;
    			if(check(mid)) r = mid - 1;
    			else l = mid + 1;
    		}	
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
    

    D

    DP方法非常显然

    但是时间复杂度不对

    又没有凸性,无法优化(至少我不会)

    只能考虑别的方法

    发现每一次分段其实就是加上某一个后缀的值

    很显然某个后缀只能加一次

    所以题目变成了求([2,n])的前(k - 1)大的后缀的和

    最后将答案加上权值总和

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    #include<vector>
    #include<ctime>
    #include<cmath>
    #define LL long long
    #define pii pair<LL,LL>
    #define mk make_pair
    #define fi first
    #define se second
    using namespace std;
    const int N = 5e5 + 3;
    const LL INF = 1e15;
    LL a[N];
    LL sum[N];
    LL maxx[N];
    int n,k;
    int tag[N];
    priority_queue <pii> q;
    inline int read(){
    	int v = 0,c = 1;char ch = getchar();
    	while(!isdigit(ch)){
    		if(ch == '-') c = -1;
    		ch = getchar();
    	}
    	while(isdigit(ch)){
    		v = v * 10 + ch - 48;
    		ch = getchar();
    	}
    	return v * c;
    }
    int main(){
    	
    	n = read(),k = read();
    	for(int i = 1;i <= n;++i) a[i] = read(),maxx[i] = -INF;
    	maxx[n] = sum[n] = a[n];
    	q.push(mk(sum[n],n));
    	for(int i = n - 1;i >= 1;--i){
    	//	cout << i << endl;
    		sum[i] = sum[i + 1] + a[i];
    		maxx[i] = max(maxx[i + 1],sum[i]);
    		if(i != 1) q.push(mk(sum[i],i));
    	}
    	LL ans = sum[1];
    	//cout << "GG" << endl;
    	for(int i = 1;i < k;++i,q.pop()){
    		ans += q.top().fi;
    	}
    	cout << ans;
    	return 0;
    }
    
    

    F

    方法一;考虑分治

    题目中要求的区间转化一下就是下面两个条件

    区间([l,r])合法当且仅当

    (1) 区间最大值为(r - l + 1)

    (2) 区间无重复元素

    我们考虑每次按照最大值去分治

    考虑跨过最大值的贡献

    接下来要满足第二个条件

    我们设(pre_i)(a_i)上一次出现的位置

    (max_i)(pre_i)的前缀max

    发现区间([l,r])无重复元素的意思是

    (max_r < l)

    就是每个数上一次出现的位置都在(l)左边

    由于区间最大值就是区间长度

    我们就可以通过枚举一边寻找另一边的方式求解

    方法二;

    我们给每一个数随机分配一个(128)位的数字

    所以区间([L,R])符合条件

    就可以用前缀异或去表示

    由于合法区间一定包含(1)

    我们就从一个(1)开始到下一个(1)为止去寻找最大值在右边的贡献

    之后把数组反过来再来一遍

    这样(1)可能会被计算两边,特判就好。

  • 相关阅读:
    Jmeter Ant Task如果报告中有错误,在邮件内容里面直接显示出来 系列2
    自动化测试的点点滴滴经验积累
    Java中通过SimpleDateFormat格式化当前时间:/** 输出格式:20060101010101001**/
    Good Bye 2015 A
    Codeforces Round #337 (Div. 2)B
    Codeforces Round #337 (Div. 2) A水
    hdu 1698 线段树 区间更新 区间求和
    hdu 1166线段树 单点更新 区间求和
    HDU2841 (队列容斥)
    15ecjtu校赛1006 (dfs容斥)
  • 原文地址:https://www.cnblogs.com/wyxdrqc/p/11385714.html
Copyright © 2011-2022 走看看