zoukankan      html  css  js  c++  java
  • 贪心+离散化+线段树上二分。。。 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest G. Of Zorcs and Axes

    题目链接:http://codeforces.com/gym/101149/problem/G

    题目大意:给你n对数字,为(a[i], b[i]),给你m对数字,为(w[i], c[i])。给n对数字找配对,这个配对必须是m中的,而且m中的每个只能和n中的配对一次。

    配对条件,w[i]>=a[j], c[i]>=b[j]即可配对。

    输出n个数字,每个数字在m个数字当中的配对。

    思路:假定n对数字的是x,m对数字的是y

    离散化以后sort一下x和y,这样我们就得到了第一维是排序好了的。

    然后我们暴力x,每次都把a[i]的值相同的放入线段树,线段树里面储存的是b[i]。

    然后如果a[i] != a[i+1],那么我们就暴力y,对于y,暴力其中所有的w[j] < a[i+1]的,然后再线段树中找离c[i]左边最近的那个数字即可。

    ORZ,第一次知道queue这么消耗空间,一直MLE了。

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int inf = 0x3f3f3f3f;
    const int maxn = 4e5 + 5;
    const int maxf = 2e5 + 5;
    int n, m;
    pair<int, pair<int, int> > a[maxf];
    pair<int, pair<int, int> > b[maxf];
    vector<int> ve;
    vector<int> que[maxn * 2];
    /*
    线段树上二分,每次找到和当前的pos最靠近的左端的即可。并且每次保存id
    */
    struct Tree{
        int cost;
        int lft;
    }tree[maxn << 3];
    int ans[maxf];
    
    int update(int pos, int l, int r, int o, int add, int ID = 0){
        if (pos == l && pos == r){
            tree[o].cost += add;
            if (add == 1) {que[l].push_back(ID); return 0;}
            if (add == -1) {
                ID = que[l][tree[o].lft]; tree[o].lft++; return ID;
            }
        }
        int mid = (l + r) / 2;
        int id = 0;
        if (pos <= mid) id = update(pos, l, mid, o << 1, add, ID);
        if (pos > mid) id = update(pos, mid + 1, r, o << 1 | 1, add, ID);
        tree[o].cost = tree[o << 1].cost + tree[o << 1 | 1].cost;
        return id;
    }
    
    int query(int ql, int qr, int l, int r, int o){
        if (l == r){
            return l;
        }
        int mid = (l + r) / 2;
        int res = 0;
        if (qr > mid && tree[o << 1 | 1].cost > 0)
            res = max(res, query(ql, qr, mid + 1, r, o << 1 | 1));
        if (res == 0 && ql <= mid && tree[o << 1].cost > 0)
            res = max(res, query(ql, qr, l, mid, o << 1));
        return res;
    }
    
    void solve(){
        int len = ve.size();
        int pos2 = 1;
        while (b[pos2].fi < a[1].fi) pos2++;
        a[n + 1] = mk(inf, mk(inf, inf));
        for(int i = 1; i <= n; i++){
            update(a[i].se.fi, 1, len, 1, 1, a[i].se.se);
            if(a[i].fi != a[i + 1].fi) {
                while (pos2 <= m && b[pos2].fi < a[i + 1].fi){
                    if (tree[1].cost != 0){
                        int x = query(1, b[pos2].se.fi, 1, len, 1);
                        if (x){
                            int id = update(x, 1, len, 1, -1);
                            ans[id] = b[pos2].se.se;
                        }
                    }
                    pos2++;
                }
            }
        }
        for (int i = 1; i <= n; i++){
            if (ans[i] == 0) {
                printf("-1
    "); return;
            }
        }
        for (int i = 1; i <= n; i++){
            printf("%d%c", ans[i], i == n ? '
    ' : ' ');
        }
    }
    
    int main(){
        scanf("%d", &n);
        for (int i = 1; i <= n; i++){
            scanf("%d%d", &a[i].fi, &a[i].se.fi);
            a[i].se.se = i;
            ve.push_back(a[i].fi);
            ve.push_back(a[i].se.fi);
        }
        scanf("%d", &m);
        for (int i = 1; i <= m; i++){
            scanf("%d%d", &b[i].fi, &b[i].se.fi);
            b[i].se.se = i;
            ve.push_back(b[i].fi);
            ve.push_back(b[i].se.fi);
        }
        if (n > m) {
            printf("-1
    "); return 0;
        }
        sort(ALL(ve));
        ve.erase(unique(ve.begin(), ve.end()), ve.end());
        for (int i = 1; i <= n; i++){
            a[i].fi = lower_bound(ALL(ve), a[i].fi) - ve.begin() + 1;
            a[i].se.fi = lower_bound(ALL(ve), a[i].se.fi) - ve.begin() + 1;
        }
        for (int i = 1; i <= m; i++){
            b[i].fi = lower_bound(ALL(ve), b[i].fi) - ve.begin() + 1;
            b[i].se.fi = lower_bound(ALL(ve), b[i].se.fi) - ve.begin() + 1;
        }
        sort(a + 1, a + 1 + n);
        sort(b + 1, b + 1 + m);
        solve();
        return 0;
    }
    View Code
  • 相关阅读:
    Java中Runnable和Thread的区别
    Callable,Runnable比较及用法
    如何实现视差滚动效果的网页?
    【175】Easy CHM的使用
    【174】C#添加非默认字体
    【173】双显示器随便切换位置
    【172】outlook邮箱设置
    【171】IDL读取HDF文件
    怎样实现二级联动
    Java 23种设计模式详尽分析与实例解析之二--结构型模式
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6816851.html
Copyright © 2011-2022 走看看