• CodeForces round 967 div2 题解(A~E)


    本来准备比完赛就写题解的, 但是一拖拖了一星期, 唉

    最后一题没搞懂怎么做,恳请大神指教

    欢迎大家在评论区提问.

    A

    稳定版题面 https://cn.vjudge.net/problem/CodeForces-967A

    水题, 不写题解了, 浪费空间

    细节处理见代码

    #include<bits/stdc++.h>
    #define int long long
    using namespace std; 
    
    struct tim{
    	int h, m;
    }t[1001];
    int gap(int i, int j){
    	return (t[j].h - t[i].h)*60 + t[j].m - t[i].m;
    }
    
    void print(int i, int dur){ //自动把分钟的延迟进位到小时
    	t[i].m += dur;
    	while(t[i].m >= 60){
    		t[i].m -= 60;
    		t[i].h ++;
    	}
    	cout<<t[i].h<<' '<<t[i].m<<endl;
    } 
    
    int n, s;
    
    signed main(){
    	cin>>n>>s;
    	t[0].h = t[0].m = 0;
    	for(int i = 1; i <= n; i++)
    		cin>>t[i].h>>t[i].m;
    	t[n+1].h = t[n+1].m = 1000001;
    	if(gap(0,1) >= s+1){
    		cout<<0<<' '<<0<<endl;
    		return 0;
    	}
    	
    	for(int i = 1; i <= n; i++)
    		if(gap(i,i+1) >= 2*s+2) {
    			print(i,s+1);
    			break;
    		}
    	return 0;
    }
    

    B

    稳定版题面

    我没看官方题解, 我的做法是二分答案.

    二分答案判定还是很方便的. 只需要贪心堵上出水量最大的孔(特判第一个孔)


    #include<bits/stdc++.h>
    #define int long long
    using namespace std; 
    
    const int maxn = 1e5+5;
    int s[maxn],a[maxn],n,A,B;
    
    bool cmp(int a, int b){return a>b;}
    
    bool check(int pos){
    	return a[1]*A/(s[pos]) >= B;
    }
    
    signed main(){
    	cin>>n>>A>>B>>a[1];
    	for(int i = 2; i <= n; i++) cin>>a[i];
    	sort(a+2,a+n+1);//特判a[1]
    	
    	s[0] = 0;
    	for(int i = 1; i <= n; i++) s[i] = s[i-1] + a[i];
    	//l意为最多不堵多少个孔(区间左闭右开)
    	int l = 1, r = n+1, mid = (l+r)>>1;
    	while(r - l > 1){
    		mid = (l+r)>>1;
    		if(check(mid)) l = mid;
    		else r = mid;
    	}
    	cout<<n-l<<endl;
    	return 0;
    }
    
    
    
    C

    稳定版题面

    因为电梯和楼梯在所有楼层都有, 而且所有电梯速度一样,所以不用换电梯/楼梯, 直达最优

    所以易知: 距离任意一个端点的水平距离最近的电梯/楼梯最优. 我们可以用lower_bound查找最近的电梯/楼梯

    画一下图, 分类讨论一下很容易理解. 

    有一个小技巧: 把不合法的状态(找不到)设成inf,这样就不要特判了

    再算一下坐电题和走楼梯哪种更优.

    注意考虑不需要坐电梯/楼梯的情况!!! 我因为没考虑这种情况被hack了, 伤心...


    代码

    #include<bits/stdc++.h>
    #define int long long
    using namespace std; 
    
    const int maxn = 1e5+5;
    int n,m, l[maxn], e[maxn] ,v, q, cl, ce;
    
    inline int divis(int a, int b){
    	if(a % b == 0) return a / b;
    	else return a/b + 1;
    }
    
    signed main(){
    	cin>>n>>m>>cl>>ce>>v;
    	memset(l, 0x3f, sizeof l);
    	memset(e, 0x3f, sizeof e);
    	for(int i = 1; i <= cl; i++)
    		cin>>l[i];
    	for(int i = 1; i <= ce; i++)
    		cin>>e[i];
    	cin>>q;
    	while(q--){
    		int ans = 1e15+5, x1, y1, x2, y2;
    		cin>>x1>>y1>>x2>>y2;
    		if(x1 > x2){
    			swap(x1,x2);
    			swap(y1,y2);
    		}
    		if(x1 == x2){
    			cout<<abs(y1 - y2)<<endl;
    			continue; 
    		}
    		//by walk(no stairs or elevators needed)
    		int pos1 = lower_bound(l+1, l+cl+1, y1) - l, ans1 = 1e15+5, pos2, ans2;
    		if(pos1 > 1) pos2 =upper_bound(l+1, l+cl+1, y1) - l - 1, 
    			ans1 = min(abs(y1 - l[pos1])+abs(y2 - l[pos1]), abs(y1 - l[pos2])+abs(y2 - l[pos2]))
    				+ abs(x1 - x2);
    		else ans1 = abs(y1 - l[pos1])+abs(y2 - l[pos1])+ abs(x1 - x2);
    		//by stairs
    		pos1 = lower_bound(e+1, e+ce+1, y1) - e, ans2 = 1e15+5;
    		if(pos1 > 1) pos2 =upper_bound(e+1, e+ce+1, y1) - e - 1, 
    			ans2 = min(abs(y1 - e[pos1])+abs(y2 - e[pos1]), abs(y1 - e[pos2])+abs(y2 - e[pos2]))
    				+ divis(abs(x1 - x2), v);
    		else ans2 = abs(y1 - e[pos1])+abs(y2 - e[pos1])+ divis(abs(x1 - x2),v);
    		//by elevator
    		ans = min(ans1, ans2);
    		cout<<ans<<endl;
    	}
    	return 0;
    }

    D

    想出了正解, 没时间写了...

    先把所有服务器排个序

    可以发现每个service最优的选择策略 选择的server 在排序后的序列中都是连续的

    预处理出对于一个service, 以第 i 个server (或之后的server)开头, 最少选几个server

    然后暴力枚举即可

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    
    template<typename T>
    void read(T &ans){T f = 1; char c = getchar();ans = 0;while(!isdigit(c)){if(c == '-')f = -1;c = getchar();}while( isdigit(c)){ans = ans*10 + c - '0';c = getchar();}ans *= f;}
    
    const int maxn = 3e5 + 5, inf = 1e15;
    struct server{
    	int c, ord;
    	inline bool operator <(const server &rhs) const{
    		return c < rhs.c;
    	}
    }s[maxn];
    int x1, x2, cnt1[maxn], cnt2[maxn], p1, p2, n;
    
    inline int divis(int a, int b){
    	if(a % b == 0) return a / b;
    	else return a/b + 1;
    }
    
    signed main(){
    	read(n), read(x1), read(x2);
    	for(int i = 1; i <= n; i++){
    		read(s[i].c); s[i].ord = i;
    	}
    
    	sort(s + 1, s + n + 1);
    	memset(cnt1, 0x3f, sizeof cnt1); 
    	memset(cnt2, 0x3f, sizeof cnt2); 
    	for(int i = 1; i <= n; i++){
    		cnt1[i] = divis(x1, s[i].c);
    		cnt2[i] = divis(x2, s[i].c);
    	}
    
    	p1 = p2 = inf;
    	for(int i = 1; i <= n; i++){
    		if(i + cnt1[i] <= n && cnt1[i] + cnt2[i + cnt1[i]] + i - 1 <= n){
    			p1 = i, p2 = i + cnt1[i];
    			break;
    		}
    		if(i + cnt2[i] <= n && cnt2[i] + cnt1[i + cnt2[i]] + i - 1 <= n){
    			p1 = i + cnt2[i], p2 = i;
    			break;
    		}
    	}
    	if(p1 == inf){
    		puts("No");
    	}
    	else {
    		puts("Yes");
    		printf("%lld %lld
    ", cnt1[p1], cnt2[p2]);
    		for(int i = p1; i < p1 + cnt1[p1]; i++){
    			printf("%lld ", s[i].ord);
    		}
    		puts("");
    		for(int i = p2; i < p2 + cnt2[p2]; i++){
    			printf("%lld ", s[i].ord);
    		}
    		puts("");
    	}
    	return 0;
    }
    

    未完待续.....

  • 相关阅读:
    VS2015新建项目无法选择framework 4.6.2
    AngularGauge 属性解析(转载)
    JAVA基础总结2
    JAVA基础总结
    今天做项目用到框架,关于angual,然后自己整理了一番,自己上网也看了看。
    晚上闲来无事,整理一下字符串和数组常用的方法,分享给大家。
    今天写项目时,突然发现canvas的一些公式不记得了,所以整理了一番,分享给大家。
    在公司没事,随手写写
    今天做项目时,用到了好多关于js的知识点,有的忘记了,然后晚上回来自己整理一番,明天继续整理。哈哈,分享给大家。
    DOM相关知识点以及原型
  • 原文地址:https://www.cnblogs.com/Eroad/p/9373473.html
Copyright © 2020-2023  润新知