返回顶部

2014-2015 ACM-ICPC, NEERC, Southern Subregional Contest

2014-2015 ACM-ICPC, NEERC, Southern Subregional Contest)

D. Data Center

  • 题意:给你\(n\)个数对,\(a_i\)表示权值,\(l_i\)表示标识,你需要选择最少的数对使得总权值不小于\(m\)并且尽可能选择表示为\(1\)的数对

  • 题解:首先第一个条件是总权值不小于\(m\),那么先对权值排序然后求出最少需要多少数对,之后再分\(0\)\(1\)按权值进行排序,求出分别的前缀和,遍历\(1\)的数对判断是否合法即可.

  • 代码

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
     
    int n;
    ll m;
    struct Node{
        ll a;
        int l;
        int id;
    }e[N];
    int pos;
    ll sum0[N],sum1[N];
     
    int main() {
        scanf("%d %lld",&n,&m);
     
        for(int i=1;i<=n;++i){
            scanf("%lld %d",&e[i].a,&e[i].l);
            e[i].id=i;
            if(e[i].l==1) pos++;
        }
        
        sort(e+1,e+1+n,[&](Node x,Node y){
            if(x.a!=y.a) return x.a>y.a;
            return x.l>y.l;
        });
        int cnt=0;
        ll sum=0;
        for(int i=1;i<=n;++i){
            sum+=e[i].a;
            cnt++;
            if(sum>=m){
                break;
            }
        }
        sort(e+1,e+1+n,[&](Node x,Node y){
            if(x.l!=y.l) return x.l>y.l;
            return x.a>y.a;
        });
        int mx=0;
        for(int i=1;i<=pos;++i){
            sum1[i]=sum1[i-1]+e[i].a;
        }
        for(int i=pos+1;i<=n;++i){
            sum0[i]=sum0[i-1]+e[i].a;
        }
        for(int i=1;i<=min(pos,cnt);++i){
           ll res1=sum1[i];
           ll res2=sum0[pos+cnt-i];
           if(res1+res2>=m) mx=i;
        }
        printf("%d %d\n",cnt,mx);
        for(int i=1;i<=mx;++i) printf("%d ",e[i].id);
        for(int i=pos+1;i<pos+1+cnt-mx;++i) printf("%d ",e[i].id);
        return 0;
    }
    

E. Election of a Mayor

  • 题意:两个市长进行选举,有\(n\)个州,每个州都对这两个市长分开投票,当某个市长的票数大于总票数/2时,赢得这个州的支持,当某个市长的州支持数大于总州数/2时,赢得选举,现在第一个市长想要赢得选举,他可以作弊,将两个相邻州的票数合到一起,问最少作弊多少次他可以赢得选举。

  • 题解:直接模拟就好,不难发现,当第一个市长票数相平或者连续两个州都输或者连续两个州赢了一次,都可以进行合并,同时判断是否合法即可。

  • 代码

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
     
    int n;
    struct Node{
        int m,r;
        int win;
    }e[N];
    vector<PII> ans;
     
    int main() {
        scanf("%d",&n);
        int cnt1=0;
        for(int i=1;i<=n;++i){
            scanf("%d %d",&e[i].m,&e[i].r);
            if(e[i].m>e[i].r) cnt1++,e[i].win=1;
            else e[i].win=0;
        }
        int len=max(0,n-(cnt1*2-1));
        int cur=0;
        if(len!=0){
            for(int i=1;i<n;){
                if((e[i].win+e[i+1].win==0) || (e[i].win+e[i+1].win==1 && e[i].m+e[i+1].m>e[i].r+e[i+1].r)){
                    cur++;
                    ans.pb({i,i+1});
                    i+=2;
                    if(cur>=len) break;
                }
                else i++;
            }
        }
        if(cur<len) puts("-1");
        else{
            printf("%d\n",len);
            for(auto w:ans) printf("%d %d\n",w.fi,w.se);
        }
        return 0;
    }
    

F. Ilya Muromets

  • 题意:长度为\(n\)的数组,选择两个不相交的长度为\(k\)的子数组使得总和最大。

  • 题解:先记录前缀和与后缀和,然后再维护前缀和与后缀和的最大值,最后枚举断点维护答案最大值

  • 代码

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
     
    int n,k;
    int a[N];
    ll dp[2][N];
     
    int main() {
        scanf("%d %d",&n,&k);
     
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        for(int i=1;i<=n;++i){
            dp[0][i]=dp[0][i-1]+a[i];
            if(i>k) dp[0][i]-=a[i-k];
        }
        for(int i=n;i>=1;--i){
            dp[1][i]=dp[1][i+1]+a[i];
            if(n-i+1>k) dp[1][i]-=a[i+k];
        }
        for(int i=1;i<=n;++i) dp[0][i]=max(dp[0][i],dp[0][i-1]);
        for(int i=n;i>=1;--i) dp[1][i]=max(dp[1][i],dp[1][i+1]);
        ll ans=0;
        for(int i=0;i<=n+1;++i){
            ans=max(ans,dp[0][i]+dp[1][i+1]);
        }	
        printf("%lld\n",ans);
        return 0;
    }
    

G. FacePalm Accounting

  • 题意:长度为\(n\)的数组,每次可以修改一个数,将该数改成不小于数组最小值的一个数,问你最少总共需要修改多大的值使得每个长度为\(k\)的区间和都小于0

  • 题解:因为区间长度固定为\(k\),那么就非常的好写,首先贪心,每次修改区间右边界一定最优,然后因为最小值有下界,当某个数达到下界后我们就继续往左看,暴力跑会挂,但我们发现达到下界的数是不断向左连续线性的,那么我们可以直接跳过这段数,这里用链表和并查集区间染色都行,此时的复杂度就被降了下来(具体多少我不会算qwq)

  • 代码:

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
     
    int n,k;
    int a[N],b[N];
    int mi=INF;
    int p[N];
     
    int find(int x){
        if(p[x]!=x) p[x]=find(p[x]);
        return p[x];
    }
     
    int main() {
        scanf("%d %d",&n,&k);
     
        for(int i=1;i<=n;++i) scanf("%d",&a[i]),mi=min(mi,a[i]),b[i]=a[i];
        for(int i=0;i<=n;++i) p[i]=i;
        ll now=0; 
        ll ans=0;
        for(int i=1;i<=n;++i){
           now+=a[i];
           if(i>k) now-=a[i-k];
           if(i>=k){
               if(now>=0){
                   int j=i;
                   ll tmp=now+1;
                   ans+=tmp;
                   while(tmp){
                       if(a[j]-mi>=tmp){
                           now-=tmp;
                           a[j]-=tmp;
                           tmp=0;
                       }
                       else{
                           tmp-=(a[j]-mi);
                           now-=(a[j]-mi);
                           a[j]=mi;
                           p[j]=j-1;
                       }
                       j=p[j-1];
                   }
               }
           }
        }
        printf("%lld\n",ans);
        for(int i=1;i<=n;++i) printf("%d ",a[i]);
        return 0;
    }
    

I. Sale in GameStore

签到,直接模拟

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
 
int n;
int a[N];
 
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i]);
    }
    if(n==1){
        puts("1");
        return 0;
    }
    sort(a+1,a+1+n);
    ll sum=0;
    for(int i=1;i<=n;++i){
        if(sum+a[i]>a[n]){
            printf("%d",i);
            return 0;
        }
        sum+=a[i];
    }
    return 0;
}

M. Variable Shadowing

判断变量是否命名冲突,对每一层开桶记录就好

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
 
int n;
unordered_map<char,PII> mp[N];
string s;
char stk[N];
int cnt,now;
 
int main() {
    cin>>n;
    getchar();
    for(int i=1;i<=n;++i){
        getline(cin,s);
        for(int j=0;j<(int)s.size();++j){
            //cout<<i<<' '<<j<<' '<<s[j]<<' ';
            if(s[j]=='{') stk[++cnt]=s[j],now++;
            if(s[j]=='}'){
                if(stk[cnt]=='{'){
                    cnt--;
                    mp[now--].clear();
                }
                else stk[++cnt]='}';
            }
            if(s[j]>='a' && s[j]<='z'){
                for(int k=cnt;k>=0;--k)
                if(mp[k].count(s[j])){
                    cout<<i<<":"<<j+1<<":"<<" warning: shadowed declaration of "<<s[j]<<","<<" the shadowed position is "<<mp[k][s[j]].fi<<":"<<mp[k][s[j]].se<<endl;
                    break;
                }
                mp[cnt][s[j]]={i,j+1};
            }
        }
    }	
    return 0;
}开多个栈直接模拟
posted @ 2021-11-18 12:02  Rayotaku  阅读(50)  评论(0编辑  收藏  举报