zoukankan      html  css  js  c++  java
  • 【日记】12.24/【题解】CF #610 (Div.2)

    12.24

    DP

    1.洛谷P1880:环形石子合并

    思路:对于直线形,就是枚举所有区间,dp[i][j]表示i-j石子合并后的最小或最大代价,之后枚举分点来转移,因此时间复杂度(O(n^3))。遍历时按照长度来从小到大求解。

    环形的话,延长两倍,但枚举len时上限仍然为n-1。最后遍历所有长度为n-1的区间,取最大或最小即可。

    题解:

    #include<bits/stdc++.h>
    using namespace std;
    const int M=4e2+20;
    struct Stone{
    	int n,a[M],dp[M][M],sum[M],dp2[M][M];
    	void init(){
    		scanf("%d",&n);
    		for(int i=1;i<=2*n;++i)
    			for(int j=i;j<=2*n;++j)
    				dp2[i][j]=1e9+7;
    		for(int i=1;i<=n;++i)
    			scanf("%d",&a[i]),a[i+n]=a[i];
    		for(int i=1;i<=2*n;++i)
    			dp[i][i]=dp2[i][i]=0,sum[i]=sum[i-1]+a[i];
    	}
    	inline int query(int l,int r){
    		return sum[r]-sum[l-1];
    	}
    	void run(){
    		for(int len=2;len<=n;++len)
    			for(int i=1,j=len;j<=2*n;++i,++j)
    				for(int k=i;k<=j-1;++k)
    					dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+query(i,j)),
    					dp2[i][j]=min(dp2[i][j],dp2[i][k]+dp2[k+1][j]+query(i,j));
    		int mn=1e9+7,mx=0;
    		for(int i=1;i<=n;++i)
    			mn=min(mn,dp2[i][i+n-1]),mx=max(mx,dp[i][i+n-1]);
    		printf("%d
    %d
    ",mn,mx);
    	}
    }s;
    int main(){
    	s.init(),s.run();
    	return 0;
    }
    

    CF #610(div. 2)

    A.Temporarily unavailable

    题意:一维数轴,一个人要从a走到b,速度1/s,有一个基站在c,信号范围为r,问路程中有多少时间是没有信号的。

    思路:实际上就是求线段[a,b]和[c-r,c+r]的交集。除了完全不相交的情况需要特判为0之外,其余情况可以

    lf=max(lf,a),rt=min(rt,b),
    printf("%d
    ",b-a-(rt-lf));
    

    来实现。

    #include<bits/stdc++.h>
    using namespace std;
    struct Task{
    	int a,b,c,r;
    	int lf,rt;
    	void init(){
    		scanf("%d%d%d%d",&a,&b,&c,&r);
    		if (a>b)
    			swap(a,b);
    		lf=c-r,rt=c+r;
    	}
    	void run(){
    		init();
    		if (rt<a||lf>b)
    			printf("%d
    ",b-a);
    		else
    			lf=max(lf,a),rt=min(rt,b),
    			printf("%d
    ",b-a-(rt-lf));
    	}
    }t;
    int main(){
    	int T;
    	scanf("%d",&T);
    	for(int i=1;i<=T;++i)
    		t.run();
    	return 0;
    }
    

    B.K for the Price of One (Hard Version)

    题意:有n个物品,给定k。要么只买一个,花a[i]元,要么买恰好k个,只付最大的钱,一共有p块钱,问最多能买多少个物品。(简单版本为k=2)

    思路:首先按价格从小到大排序,确定恰好买k个的情况,总共有k种,即购买1-k,k+1-2k,2k+1-3k……;2-k+1,k+2-2k+1,2k+2-3k+1……;每种情况都从小到大遍历,直到买不了为止。之后,每种情况如果还有剩余,还可以单独购买前面没买的剩下的东西,记录前缀和,每次二分找<=剩余钱的最大数的位置,相加即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define mid ((l+r+1)>>1)
    #define db(x) cout<<#x<<":"<<x<<endl;
    const int M=4e5+20;
    struct Task{
    	int n,p,k,a[M];
    	void init(){
    		scanf("%d%d%d",&n,&p,&k);
    		for(int i=1;i<=n;++i)
    			scanf("%d",&a[i]);
    	}
    	bool check(int x){
    		int ans=0;
    		while(x-k>=0)
    			ans+=a[x],x-=k;
    		for(int i=x;i>=1;--i)
    			ans+=a[i];
    		if (ans<=p)
    			return true;
    		return false;
    	}
    	void run(){
    		init();
    		sort(a+1,a+n+1);
    		int l=k,r=n;
    		while(l!=r){
    			if (check(mid))
    				l=mid;
    			else
    				r=mid-1;
    			db(l);
    			db(r);
    		}
    		if (l==k&&!check(l)){
    			int ans=0,pt=0;
    			while(ans+a[pt+1]<=p)
    				++pt,ans+=a[pt];
    			printf("%d
    ",pt);
    		}
    		else
    			printf("%d
    ",l);
    	}
    }t;
    int main(){
    	int T;
    	scanf("%d",&T);
    	for(int i=1;i<=T;++i)
    		t.run();
    	return 0;
    }
    

    C.Petya and Exam

    题意:考试有T分钟,n道题目,简单题目amin切,困难题目bmin切,可以随时离场。每道题目还有一个截止时间(t_i),若在s分钟离场,但存在题目(t_i<=s),那么就0分,否则就是做出来题目的个数为得分。问最大得分是多少。

    思路:一开始思考,最优策略肯定是按照截止时间从小到大开始做(不论难易),所以先排序,从小到大开始做,如果做完一道题之后发现可以离场,那就记录一下题目个数,否则就必须继续做(这个可以用v[p+1].mant和t的比较来判断)。但这样过不了样例。问题在于,如果b>>a,那么做完一道难题之后,最优策略有可能是在下一个b的mant到来之前,先疯狂切简单题,这样反而答案更优,那就每次做完题之后再看看全切水题能多少分即可,更新最大值。

    #include<bits/stdc++.h>
    using namespace std;
    const int M=4e5+20;
    struct Prob{
    	int diff,mant;
    	bool operator<(const Prob &x)const{
    		return mant<x.mant||(mant==x.mant&&diff<x.diff);
    	}
    };
    struct Task{
    	int n,T,a,b,numa;
    	Prob v[M];
    	void init(){
    		numa=0;
    		scanf("%d%d%d%d",&n,&T,&a,&b);
    		for(int i=1;i<=n;++i)
    			scanf("%d",&v[i].diff),numa+=(v[i].diff?0:1);
    		for(int i=1;i<=n;++i)
    			scanf("%d",&v[i].mant);
    		sort(v+1,v+n+1);
    		v[n+1].mant=T+1;
    	}
    	void run(){
    		init();
    		int mx=max(0,min(numa,(v[1].mant-1)/a)),now=0,t=0;
    		for(int i=1;i<=n;++i){
    			++now;
    			if (v[i].diff)
    				t+=b;
    			else
    				t+=a,--numa;
    			if (t>T)
    				break;
    			if (t<v[i+1].mant)
    				mx=max(mx,now+min(numa,(v[i+1].mant-t-1)/a));
    		}
    		printf("%d
    ",mx);
    	}
    }t;
    int main(){
    	int T;
    	scanf("%d",&T);
    	for(int i=1;i<=T;++i)
    		t.run();
    	return 0;
    }
    

    D.Enchanted Artifact

    题意:一个密码锁,密码为长度<=300的,由a和b组成的字符串。每次你输入密码会返回一个耐久,耐久为最小删除/插入/修改的次数使得你输入的密码和答案相同的次数。给你n+2次机会尝试。n不知道。

    题意:首先求出a和b的个数,方法是用300的a和300的b去试,那么a的个数就是300-c1,b的个数就是300-c2。那么len=c1+c2。之后c2表示还缺的b的个数。以len个a的字符串为基准开始试,每次修改一位为b。如果答案比c2小,说明改对了,这位就是b,--c2。如果答案比c2大,说明改错了,这位是a,就改回去,c2不变。最后一共用了n+2次。

    #include<bits/stdc++.h>
    using namespace std;
    const int M=300;
    int main(){
    	string s=string(M,'a');
    	int c1,c2;
    	cout<<s<<endl;cout.flush();
    	scanf("%d",&c1);
    	c1=300-c1;
    	s=string(M,'b');
    	cout<<s<<endl;cout.flush();
    	scanf("%d",&c2);
    	c2=300-c2;
    	if (c1==0){
    		s=string(c2,'b');
    		cout<<s<<endl;cout.flush();
    		scanf("%d",&c2);
    		return 0;
    	}
    	else if (c2==0){
    		s=string(c1,'a');
    		cout<<s<<endl;cout.flush();
    		scanf("%d",&c1);
    		return 0;
    	}
    	int len=c1+c2;
    	s=string(len,'a');
    	int c=0;
    	for(int i=0;i<len-1;++i){
    		s[i]='b';
    		cout<<s<<endl;cout.flush();
    		scanf("%d",&c);
    		if (c==0)
    			return 0;
    		if (c>c2)
    			s[i]='a';
    		else
    			--c2;
    	}
    	if(c2)
    		s[len-1]='b';
    	cout<<s<<endl;cout.flush();
    	scanf("%d",&c);
    	return 0;
    }
    
  • 相关阅读:
    JVM源码分析 规格严格
    Smack 规格严格
    Java动态编译 规格严格
    RPM仓库地址 规格严格
    使用控制台程序测试DLL依赖
    TestNG 使用入门
    白羊座二:星星的一周
    路遇两骗子
    《落地,请开手机》里面最经典的一句台词
    今天明白的一个道理
  • 原文地址:https://www.cnblogs.com/diorvh/p/12095507.html
Copyright © 2011-2022 走看看