Codeforces Round #509 (Div. 2) 解(bu)题记录

看到某神叉每天都关注访问量...所以我也来蹭热度

不断学习别人的代码,才是一种进步,....同一个题...为什么他们的代码这么优秀>>觉得一是思路的问题,另外就是对问题的归纳程度,当然有又臭又长的代码,倒是显得有点幼稚了....其实从简单的方面去考虑问题,也是挺不错的,一时无法抉择

----------------------------------------------------------------------------------------------------------------------

A. Heist

题意: 给定一串数字,要求添加几个数字使得这些数字连续,求最小的添加量

解题代码:

#include<bits/stdc++.h>
using namespace std;
int a[1100];
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    int ans=a[n]-a[1]+1-n;
    printf("%d\n",ans);
    return 0;
}
View Code

B. Buying a TV Set

题意:给出a,b,x,y>>  求满足 0<=x0<=a ,0<=y0<=b,且 x0/y0=x/y的整点数>>

解题代码:

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll a ,ll b){
    if(b==0) return a;
    else return gcd(b,a%b);
}
int main(){
    ll x,y,a,b,ans;
    cin>>a>>b>>x>>y;
    ll tmp=gcd(x,y);
    x/=tmp;y/=tmp;
    cout<<min(a/x,b/y);
    return 0;
}
View Code

 

C. Coffee Break

题意: 将n个组合分成m个组合,每个组合里任意两个数相差>=d(原组合不同则不必要)  求最小的m 贪心去做就好

set封装的二分应用

解题代码:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>pii;
const int N=2e5+10;
set<pii>se;int ans[N];
struct node{int x,y;}a[N];
bool cmp(node a,node b){return a.x<b.x;}
int main(){
    int n,m,d,x;scanf("%d%d%d",&n,&m,&d);
    for(int i=1;i<=n;i++){
        scanf("%d",&x);
        se.insert({x,i});
    }
    int t=0;
    while(se.size()!=0){
        t++;auto u=se.begin();ans[u->second]=t;
        int pre=u->first;u=se.erase(u);
        while(u!=se.end()){
            u=se.upper_bound({pre+d,n+1});
            if(u==se.end()) break;
            else {
                ans[u->second]=t;
                pre=u->first;
                u=se.erase(u);
            }
        }
    }
    printf("%d\n",t);
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    return 0;
}
View Code

D. Glider

题意:在云层的最左端点跳肯定是最优的,枚举每个起点,二分找到右边满足要求的右端点.求最值就好

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct node{int x,y;}a[N];
bool cmp(node a,node b){return a.x<b.x;}
int dis[N],sum[N];
int main(){
    int n,h;scanf("%d%d",&n,&h);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&a[i].x,&a[i].y); 
    }
    sort(a+1,a+n+1,cmp);
    dis[1]=0;sum[1]=a[1].y-a[1].x;dis[n+1]=1e9+1000;
    for(int i=2;i<=n;i++){dis[i]=dis[i-1]+a[i].x-a[i-1].y;sum[i]=sum[i-1]+a[i].y-a[i].x;}
    int ans=0; 
    for(int i=1;i<=n;i++){
        int p=lower_bound(dis+i,dis+n+2,h+dis[i])-dis;
        ans=max(ans,sum[p-1]-sum[i-1]);
    }
    printf("%d\n",ans+h);
    return 0;
}
View Code

E. Tree Reconstruction

E是一枚树上构造题,题意是给出n,同时给出n-1组(u,v) 代表去掉第i条边所分成的两个团中的最大节点值:

解法:首先v必须为n,其次考虑u,假如u出现一次,则将他与n节点连一条边,其次假如u出现多次的话,考虑这样构造,将n,u作为两个端点,中间依次

假如 比u小的值的节点(若不满足的话,则该情况不存在)

感觉优美的代码,思路特别清晰的代码...确实正确率很高,...一般思路不完善...代码会越丑....还不一定正确.....觉得写题前 还是得需要完整的思路

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int num[N];queue<int>q;
struct node{int x,y;}ans[N];
int main(){
    int n,x,y;scanf("%d",&n);
    int flag=1;
    for(int i=1;i<n;i++){
        scanf("%d%d",&x,&y);
        if(y!=n) flag=0;num[x]++;
    }
    if(flag==0){puts("NO");return 0;}
    int cnt=1;
    for(int i=1;i<n;i++) if(num[i]==0) q.push(i);
    for(int i=1;i<n;i++) if(num[i]){
        if(num[i]==1) ans[cnt++]={i,n};
        else{
            int p=i;
            while(num[i]!=1){
                if(q.size()==0||q.front()>=i) {
                    flag=0;puts("NO");return 0;
                }
                int v=q.front();q.pop();
                ans[cnt++]={p,v};p=v;num[i]--;
            }
            ans[cnt++]={p,n};
        }
    }
    puts("YES");
    for(int i=1;i<n;i++){
        printf("%d %d\n",ans[i].x,ans[i].y);
    }
    return 0;
}
View Code

F. Ray in the tube

显然y是没什么用的.....

考虑同一条线上的两个寄存器的间隔的一半d  假设间隔是2kd的话 那么两条边上的点分别是{kd,3kd,5kd.....}  {0,2kd,4kd,6kd,.......}  考虑k的取值,首先取不同值时,

肯定会有一些交点被包含另一种方案中,所以我们可以考虑从枚举间隔出发..

.....待补

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,y,a[N],b[N];
map<int,int>cnt1,cnt2;
int solve(int k){
    cnt1.clear();cnt2.clear();    
    for(int i=1;i<=n;i++) cnt1[a[i]%k]++;
    for(int i=1;i<=m;i++) cnt2[b[i]%k]++;
    int ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,cnt1[a[i]%k]+cnt2[(a[i]+k/2)%k]);
    for(int i=1;i<=m;i++) ans=max(ans,cnt2[b[i]%k]+cnt1[(b[i]+k/2)%k]);
    return ans;
}
int main(){
    scanf("%d%d",&n,&y);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    scanf("%d%d",&m,&y); 
    for(int i=1;i<=m;i++) scanf("%d",&b[i]);
    int ans=0;
    for(int k=2;k<=1e9;k<<=1) ans=max(ans,solve(k));
    printf("%d\n",max(ans,2));
    return 0;
}
View Code

 

  

 

 

 

转载于:https://www.cnblogs.com/vainglory/p/9663355.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值