2021.01.28 Rating

B - B

题意:有n个骑士,能量大的能杀死能量小的并吞并他的硬币,但是只能杀死k个骑士,求每个骑士可能获得的最大硬币数。

题解:先将这些骑士按能量的大小从小到大排序,因为一个骑士只能杀死能量比他小的骑士,为了使他所获得的硬币数最大,就要使他所杀死的k个骑士中所包含的硬币数最大(如果能量比他小的骑士的人数小于k,就不需要判断哪k个骑士硬币数最大)。用multiset储存骑士的硬币数,multiset多重集合容器允许重复的元素键值插入。(一开始我是按硬币数从大到小排序,再把能量小于这个骑士的加上然后就超时了)、

用multiset做的

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
typedef long long ll;
multiset<ll>s; 
multiset<ll>::iterator it; 
struct node{
    ll id;
    ll p;
    ll c;
}a[MAXN];
ll ans[MAXN];
bool cmp(node x,node y){
    return x.p<y.p;
}
int main(){
    ios::sync_with_stdio(false);
    ll n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        a[i].id=i;
        cin>>a[i].p;
    }
    for(int i=1;i<=n;i++){
        cin>>a[i].c; 
    }
    sort(a+1,a+n+1,cmp);
    int cnt=0;
    for(int i=1;i<=n;i++){
        ans[a[i].id]=a[i].c;
        for(it=s.begin();it!=s.end();it++){
            ans[a[i].id]+=*it;//先把能量小的硬币全加上 
        }
        s.insert(a[i].c);//把能量小的硬币全存进去 
        while(s.size()>k){//如果能量小的人大于k个 
            s.erase(s.begin());//就把硬币最少的删掉直到等于k个 
        }
    }
    for(int i=1;i<=n;i++){
        cout<<ans[i]<<" ";
    }
    cout<<endl;
    return 0;
}
View Code

我自己的超时

#include<algorithm>
#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
#define MAXN 100010
struct node{
    int id;
    int p;
    long long c;
    long long sum;
}a[MAXN];
bool cmp1(node x,node y){
    return x.c>y.c;
}
bool cmp2(node x,node y){
    return x.id<y.id;
}
int main(){
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        a[i].id=i;
        cin>>a[i].p;
    }
    for(int i=1;i<=n;i++){
        cin>>a[i].c; 
        a[i].sum=a[i].c;
    }
    sort(a+1,a+n+1,cmp1);
    int cnt=0;
    for(int i=1;i<=n;i++){
        cnt=0;
        for(int j=1;j<=n;j++){
            if(cnt==k){
                break;
            }
            if(a[i].p>a[j].p){
                a[i].sum+=a[j].c;
                cnt++;
            }
        }
    }
    sort(a+1,a+1+n,cmp2);
    for(int i=1;i<=n;i++){
        cout<<a[i].sum<<" ";
    }
    cout<<endl;
    return 0;
}
View Code

 

C - C

 题意:给出平行于x轴的正方形的四个顶点和与x轴成45度倾斜的正方形的四个顶点,判断两个正方形是否相交。

 题解:数据范围小,如果两个正方形相交则一定有一个整数点重合,所以判断两个正方向中是否有重合的整数点。对于倾斜的正方形,由于他的每条边的斜率都可知,可根据线性规划判读点是否属于倾斜正方形。(看了好多人做的都理解不了,只有这个做法我能整明白。)

#include<bits/stdc++.h>
using namespace std;
struct node{
    int x,y;
}p[50000],q[50000];//我开40010 RE了 
int main(){
    ios::sync_with_stdio(false);
    int x,y;
    int minx1=110,maxx1=-110,miny1=110,maxy1=-110;
    int minx2=110,maxx2=-110,miny2=110,maxy2=-110;
    for(int i=1;i<=4;i++){
        cin>>x>>y;
        minx1=min(x,minx1);
        maxx1=max(x,maxx1);
        miny1=min(y,miny1);
        maxy1=max(y,maxy1);
    }
    for(int i=1;i<=4;i++){
        cin>>x>>y;
        minx2=min(x,minx2);
        maxx2=max(x,maxx2);
        miny2=min(y,miny2);
        maxy2=max(y,maxy2);
    }
    int cnt1=0,cnt2=0;
    for(int i=minx1;i<=maxx1;i++){
        for(int j=miny1;j<=maxy1;j++){
            cnt1++;
            p[cnt1].x=i;
            p[cnt1].y=j;
        }
    }
    int a,b,c,d;
    int tx=(maxx2+minx2)/2;
    int ty=(maxy2+miny2)/2;
    for(int i=minx2;i<=maxx2;i++){
        for(int j=miny2;j<=maxy2;j++){
            a=j-ty-i+minx2;//对应的直线为y-ty=x-minx2; 
            b=j-ty-i+maxx2;//y-ty=x-maxx2;
            c=j-ty+i-maxx2;//y-ty=-(x-maxx2)
            d=j-ty+i-minx2;//y-ty=-(x-minx2)
            //因为tx,ty在正方形里,可以通过线性规划来进行判断 
            if(a<=0&&b>=0&&c<=0&&d>=0){
                cnt2++;
                q[cnt2].x=i;
                q[cnt2].y=j;
            }
        }
    }
    int flag=0;
    //依次判断有没有点重合 
    for(int i=1;i<=cnt1;i++){
        for(int j=1;j<=cnt2;j++){
            if(p[i].x==q[j].x&&p[i].y==q[j].y){
                flag=1;
            }
            if(flag) break;
        }
        if(flag) break;
    }
    if(flag){
        cout<<"YES"<<endl;
    }else{
        cout<<"NO"<<endl;
    }
    return 0;
}

 

posted @ 2021-02-02 17:32  Endeavo_r  阅读(69)  评论(0)    收藏  举报