zoukankan      html  css  js  c++  java
  • 【CF1154】题解

    A

    直接模拟即可。

    B

    对数组中的值进行排序去重。发现若去重之后的数组中有大于 3 个数时无解,因为无法找到一个点到数轴上四个点的距离均相等。若去重之后的数组中只有三个值,则判断中间的值是否到两边的值相等,若不相等,同理无解,相等则解为距离。若只有两个不同的值,若中点是整数,则答案为中点到左端点的距离,否则为两点之间的距离。若只有一个不同的值,则答案直接为 0。

    C

    首先去掉整周的情况,先统计出有多少个完整的周。剩下为出发日所在周和结束日所在周的情况。将这两周拼成一周(十四天),枚举出发的时间,计算通过当前的食物可以到达的最远距离,取最大值后加入答案贡献即可。

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define all(x) x.begin(),x.end()
    #define cls(a,b) memset(a,b,sizeof(a))
    #define debug(x) printf("x = %d
    ",x)
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    const int dx[]={0,1,0,-1};
    const int dy[]={1,0,-1,0};
    const int mod=1e9+7;
    const int inf=0x3f3f3f3f;
    //const int maxn=
    const double eps=1e-6;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll sqr(ll x){return x*x;}
    inline ll read(){
    	ll x=0,f=1;char ch;
    	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    	return f*x;
    }
    /*--------------------------------------------------------*/
    
    const int s[]={0,1,2,0,2,1,0};
    int a,b,c;
    ll ans;
    
    void read_and_parse(){
    	a=read(),b=read(),c=read();
    	ans=min(a/3,min(b/2,c/2));
    	a-=ans*3,b-=ans*2,c-=ans*2;
    	ans*=7;
    }
    
    void solve(){
    	int res=0;
    	for(int i=0;i<7;i++){
    		int ret=0,aa=a,bb=b,cc=c;
    		for(int j=i;j<i+7;j++){
    			if(s[j%7]==0){
    				if(aa)--aa,++ret;
    				else break;
    			}else if(s[j%7]==1){
    				if(bb)--bb,++ret;
    				else break;
    			}else{
    				if(cc)--cc,++ret;
    				else break;
    			}
    		}
    		res=max(res,ret);
    	}
    	printf("%lld
    ",ans+res);
    }
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    

    D

    贪心策略:在阳光下且油箱未满的时候,优先采用电平来供电,其他情况下优先采用太阳能供电。

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define all(x) x.begin(),x.end()
    #define cls(a,b) memset(a,b,sizeof(a))
    #define debug(x) printf("x = %d
    ",x)
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    const int dx[]={0,1,0,-1};
    const int dy[]={1,0,-1,0};
    const int mod=1e9+7;
    const int inf=0x3f3f3f3f;
    const int maxn=2e5+10;
    const double eps=1e-6;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll sqr(ll x){return x*x;}
    inline ll read(){
    	ll x=0,f=1;char ch;
    	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    	return f*x;
    }
    /*--------------------------------------------------------*/
    
    int n,b,a,now;
    bool s[maxn];
    
    void read_and_parse(){
    	n=read(),b=read(),a=read(),now=a;
    	for(int i=1;i<=n;i++)s[i]=read();
    }
    
    void solve(){
    	for(int i=1;i<=n;i++){
    		if(s[i]==1){
    			if(b&&now<a){
    				--b,++now;
    			}else{
    				if(now)--now;
    				else return (void)printf("%d
    ",i-1);
    			}
    		}else{
    			if(now)--now;
    			else if(b)--b;
    			else return (void)printf("%d
    ",i-1);
    		}
    	}
    	printf("%d
    ",n);
    }
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    

    E

    采用双向链表进行模拟整个过程,因为每个人会且仅会被选择一次,因此时间复杂度为 (O(n))

    By wzj_xhjbk, contest: Codeforces Round #552 (Div. 3), problem: (E) Two Teams, Accepted, #
     #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define all(x) x.begin(),x.end()
    #define cls(a,b) memset(a,b,sizeof(a))
    #define debug(x) printf("x = %d
    ",x)
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    const int dx[]={0,1,0,-1};
    const int dy[]={1,0,-1,0};
    const int mod=1e9+7;
    const int inf=0x3f3f3f3f;
    const int maxn=2e5+10;
    const double eps=1e-6;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll sqr(ll x){return x*x;}
    inline ll read(){
    	ll x=0,f=1;char ch;
    	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    	return f*x;
    }
    /*--------------------------------------------------------*/
    
    int n,k,a[maxn],d[maxn],tag[maxn],l[maxn],r[maxn];
    
    bool cmp(int x,int y){return a[x]>a[y];}
    
    void read_and_parse(){
    	n=read(),k=read();
    	for(int i=1;i<=n;i++)a[i]=read(),d[i]=i,l[i]=i-1,r[i]=i+1;// 0 ~ n+1
    	sort(d+1,d+n+1,cmp);
    }
    
    void solve(){
    	int clk=1;
    	for(int i=1;i<=n;i++){
    		if(tag[d[i]]!=0)continue;
    		tag[d[i]]=clk;
    		int pos=d[i],cnt=0,lb=0,rb=n+1;
    		while(l[pos]&&cnt<k)pos=l[pos],tag[pos]=clk,++cnt;
    		if(l[pos])lb=l[pos];
    		pos=d[i],cnt=0;
    		while(r[pos]<=n&&cnt<k)pos=r[pos],tag[pos]=clk,++cnt;
    		if(r[pos]<=n)rb=r[pos];
    		r[lb]=rb,l[rb]=lb;
    		clk=clk==1?2:1;
    	}
    	for(int i=1;i<=n;i++)printf("%d",tag[i]);
    	puts("");
    }
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    

    F

    不考虑优惠策略,可以发现买 k 个物品的最小值即为所有物品中的前 k 小值之和,因此按照物品的价格进行排序。现在考虑优惠政策,设 (dp[i]) 表示买 i 个物品的最小值,则状态转移方程为 (dp[i]=min{dp[i],dp[i-a]+sumlimits_{i=i-a+b+1}^{n}cost[i] })。其中求和部分可以利用前缀和预处理,时间复杂度为 (O(k*m))

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define all(x) x.begin(),x.end()
    #define cls(a,b) memset(a,b,sizeof(a))
    #define debug(x) printf("x = %d
    ",x)
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    const int dx[]={0,1,0,-1};
    const int dy[]={1,0,-1,0};
    const int mod=1e9+7;
    const int inf=0x3f3f3f3f;
    const int maxn=2e5+10;
    const double eps=1e-6;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll sqr(ll x){return x*x;}
    inline ll read(){
    	ll x=0,f=1;char ch;
    	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    	return f*x;
    }
    /*--------------------------------------------------------*/
    
    int n,m,k,a[maxn];
    ll dp[2010],sum[2010];
    P off[maxn];
    
    void read_and_parse(){
    	n=read(),m=read(),k=read();
    	for(int i=1;i<=n;i++)a[i]=read();
    	for(int i=1;i<=m;i++)off[i].fi=read(),off[i].se=read();
    	sort(a+1,a+n+1),sort(off+1,off+m+1);
    }
    
    void solve(){
    	for(int i=1;i<=k;i++)sum[i]=sum[i-1]+a[i],dp[i]=sum[i];
    	for(int i=1;i<=k;i++){
    		for(int j=1;j<=m;j++){
    			if(off[j].fi>i)break;
    			dp[i]=min(dp[i],dp[i-off[j].fi]+sum[i]-sum[i-off[j].fi+off[j].se]);
    		}
    	}
    	printf("%lld
    ",dp[k]);
    }
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    

    G

    玄学复杂度。。考虑枚举 (gcd),每次找到序列中最小的两个数,计算最小公倍数与最优解进行比较即可。

  • 相关阅读:
    设计模式-状态模式
    设计模式-策略模式
    Spring MVC 梳理
    Spring MVC 梳理
    设计模式-总结
    Spring boot 梳理
    Spring boot 梳理
    [DP题]最长上升子序列
    NOIP2013 Day1
    20171025日程
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10724177.html
Copyright © 2011-2022 走看看