2015-2016 Northwestern European Regional Contest (NWERC 2015)

传送门

文章目录

A

贪心+优先队列
对于每个人,计算开始时间和结束时间,按照开始时间进行排序。
使用优先队列维护最先结束的任务,如果对首结束时间和当前开始时间的差小于m,则将队首弹出,将结束时间入队,反之将队首弹出。

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n,m;
    cin>>n>>m;
    vector<pair<int,int>>v(n);
    for( int i=0;i<n;i++){
        cin>>v[i].first>>v[i].second;
        v[i].second+=v[i].first;
    }
    sort(v.begin(),v.end());
    priority_queue<int,vector<int>,greater<int>>q;
    int ans=0;
    for( int i=0;i<n;i++){
        // cout<<ans<<q.size()<<endl;
        while(!q.empty()&&q.top()+m<v[i].first){
            q.pop();
        }        
        if(!q.empty()&&q.top()>v[i].first){
            q.push(v[i].second);
            continue;
        }
        if(!q.empty()&&q.top()+m>=v[i].first){
            ans++;
            q.pop();
            q.push(v[i].second);
            continue;
        }
        else {
            q.push(v[i].second);
        }
        
    }
    cout<<ans<<endl;
    system("pause");
}

E

二分图最大匹配,网络流

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
struct Flow {
    static constexpr ll INF = 1E18;
    int n;
    struct Edge {
        int to;
        ll cap;
        Edge(int to, ll cap) : to(to), cap(cap) {}
    };
    std::vector<Edge> e;
    std::vector<std::vector<int>> g;
    std::vector<int> cur, h;
    Flow(int n) : n(n), g(n) {}
    bool bfs(int s, int t) {
        h.assign(n, -1);
        std::queue<int> que;
        h[s] = 0;
        que.push(s);
        while (!que.empty()) {
            int u = que.front();
            que.pop();
            for (int i : g[u]) {
                int v = e[i].to;
                int c = e[i].cap;
                if (c > 0 && h[v] == -1) {
                    h[v] = h[u] + 1;
                    if (v == t)
                        return true;
                    que.push(v);
                }
            }
        }
        return false;
    }
    ll dfs(int u, int t, ll f) {
        if (u == t)
            return f;
        ll r = f;
        for (int &i = cur[u]; i < int(g[u].size()); ++i) {
            int j = g[u][i];
            int v = e[j].to;
            ll c = e[j].cap;
            if (c > 0 && h[v] == h[u] + 1) {
                ll a = dfs(v, t, std::min(r, c));
                e[j].cap -= a;
                e[j ^ 1].cap += a;
                r -= a;
                if (r == 0)
                    return f;
            }
        }
        return f - r;
    }
    void addEdge(int u, int v, ll c) {
        g[u].push_back(e.size());
        e.emplace_back(v, c);
        g[v].push_back(e.size());
        e.emplace_back(u, 0);
    }
    ll maxFlow(int s, int t) {
        ll ans = 0;
        while (bfs(s, t)) {
            cur.assign(n, 0);
            ans += dfs(s, t, INF);
        }
        return ans;
    }
};
signed main(){
    int n;
    cin>>n;
    vector<pair<int,int>>v(n);
    Flow ff(n*4+10);
    int s=n*4+2,t=n*4+3;
    for( int i=0;i<n;i++){
        cin>>v[i].first>>v[i].second;
    }
    int cnt=n;
    map<ll,int>mp;
    map<int,ll>mp2;
    for( int i=0;i<n;i++){
        int x=v[i].first,y=v[i].second;
        array<ll,3>a;
        a[0]=x+y,a[1]=x-y,a[2]=x*y;
        for( int j=0;j<3;j++){
            if(mp[a[j]]==0) mp[a[j]]=++cnt;
            ff.addEdge(i,mp[a[j]],1);
        }
    }
    for( int i=0;i<n;i++){
        ff.addEdge(s,i,1);
    }
    for( int i=n+1;i<=cnt;i++){
        ff.addEdge(i,t,1);
    }
    for( auto it:mp){
        mp2[it.second]=it.first;
    }
    auto out=[&](int i,int j){
        int x=v[i].first,y=v[i].second;
        ll z=mp2[j];
        if(x+y==z) printf("%lld + %lld = %lld\n",x,y,z);
        else if(x-y==z) printf("%lld - %lld = %lld\n",x,y,z);
        else printf("%lld * %lld = %lld\n",x,y,z);
    };    
    if(ff.maxFlow(s,t)<n){
        cout<<"impossible"<<endl;
    }
    else {
        for( int i=0;i<n;i++){
            for( auto it:ff.g[i]){
                auto ee=ff.e[it];
                if(ee.cap==0){
                    out(i,ee.to);
                    break;
                }
            }
        }
    }
    system("pause");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值