codeforces div2 496

C

题意:给你 n*m 的字符串矩阵,要求删除最少的列,使得每一行的字典序大于其前面一行。

思路:我们可以从0到n-1依次判断是否需要删除该列。对于某一列,只有当出现了 某个位置小于其前面的位置,并且前面保留的列不能决定其大小,才考虑删掉。可以对每个位置设一个标志,表示这个位置是否已经被“决定了”。

#include<bits/stdc++.h>
#define SPEED_UP iostream::sync_with_stdio(false);
using namespace std;

#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))
#define urep(i, s, t) for(int (i)=(s);(i)>=(t);--(i))

typedef long long LL;

const int inf  = 0x7fffffff;
const int Maxn = 1005;

int n, m;
char a[105][105];
int flag[105];

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in", "r", stdin);
#endif
    SPEED_UP
    cin >> n >> m;
    rep(i, 0, n-1) cin >> a[i];
    int ans = 0;
    rep(k, 0, m-1) {
        int ok = 1;
        rep(i, 1, n-1) {
            if (a[i][k] < a[i-1][k]) {
                if (flag[i] == 0) {
                    ok = 0;
                    break;
                }
            }
        }
        if (ok) {
            rep(i, 1, n-1)
                if (a[i][k] > a[i-1][k]) flag[i] = 1;
        }
        else
            ++ans;
    }
    cout << ans;
    return 0;
}

D

题意:题目描述了一个赛制,每局比赛先赢t分的人赢得此局,先赢s局的人赢得整场比赛,现在给出一个序列表示每场比赛的序列,求出所有可行的s与t。

思路:从1到n枚举t即可,对于每个t,可以在最多算n/t次,总的时间复杂度是个和谐函数。

#include<bits/stdc++.h>
#define SPEED_UP iostream::sync_with_stdio(false);
using namespace std;

#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))
#define urep(i, s, t) for(int (i)=(s);(i)>=(t);--(i))

typedef long long LL;

const int inf  = 0x7fffffff;
const int Maxn = 1005;

int n, m;
char a[105][105];
int flag[105];

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in", "r", stdin);
#endif
    SPEED_UP
    cin >> n >> m;
    rep(i, 0, n-1) cin >> a[i];
    int ans = 0;
    rep(k, 0, m-1) {
        int ok = 1;
        rep(i, 1, n-1) {
            if (a[i][k] < a[i-1][k]) {
                if (flag[i] == 0) {
                    ok = 0;
                    break;
                }
            }
        }
        if (ok) {
            rep(i, 1, n-1)
                if (a[i][k] > a[i-1][k]) flag[i] = 1;
        }
        else
            ++ans;
    }
    cout << ans;
    return 0;
}

E

题意:有n个part,m个actor。每个part两个属性(ai, bi),每个actor(ci,di,ki)。一个part可以分配给一个actor,IFF ci <= ai <= bi <= di,ki是一个actor最多可以得到的part数。求所有的part是否都可以被分配给actor。

思路:将part和actor一起先根据两元组排序(actor不看ki),先按照第一个元素排,第一个元素相同的actor在前,part在后。然后建一个set,根据排序顺序依次扫描,如果是actor,加入set,如果是part,在set中以bi为lowerbound寻找actor。。就这么一个贪心 Orz。。。

#include<bits/stdc++.h>
#define SPEED_UP iostream::sync_with_stdio(false);
using namespace std;

#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))
#define urep(i, s, t) for(int (i)=(s);(i)>=(t);--(i))

typedef long long LL;
typedef pair<int, int> pi;

const int Maxn = (int)1e5+10;

int ai[Maxn], bi[Maxn], ci[Maxn], di[Maxn], ki[Maxn];

struct Node {
    int idx;
    int type;
    void GetInterval(int& l, int& r) const {
        if (type == 0) {
            l = ai[idx];
            r = bi[idx];
        } else {
            l = ci[idx];
            r = di[idx];
        }
    }
};

struct comp {
    bool operator () (const Node& lhs, const Node& rhs) const {
            int l1, l2, r1, r2;
            lhs.GetInterval(l1, r1);
            rhs.GetInterval(l2, r2);
            if (l1 == l2) {
                if (lhs.type == 0 && rhs.type == 1)
                    return false;
                else
                    return true;
            }
            else
                return l1 < l2;
    }
} Comp;

struct classcomp {
    bool operator () (const Node& lhs, const Node& rhs) const {
        int l1, l2, r1, r2;
        lhs.GetInterval(l1, r1);
        rhs.GetInterval(l2, r2);
        return r1 < r2;
    }
};

int ans[Maxn];
int n, m;

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in", "r", stdin);
#endif
    SPEED_UP
    vector<Node> arr;
    cin >> n;
    rep(i, 1, n) {
        cin >> ai[i] >> bi[i];
        arr.push_back((Node){i, 0});
    }
    cin >> m;
    rep(i, 1, m) {
        cin >> ci[i] >> di[i] >> ki[i];
        arr.push_back((Node){i, 1});
    }
/*
    if (n == 500 && ai[1] == 1 && bi[1] == 1) {
        cout << m << endl;
        rep(i, 1, m) cout << ci[i] << ' ' << di[i] << ' ' << ki[i] << endl;
        return 0;
    }
*/
    //cout << "hello" << endl;
    stable_sort(arr.begin(), arr.end(), Comp);
    //cout << "hello" << endl;
    multiset<Node, classcomp> s;
    int nSize = arr.size();
    int ok = 1;
#ifndef ONLINE_JUDGE
    rep(i, 0, nSize-1) cout << "(" << arr[i].idx << "," << arr[i].type << ")" << ' ';cout << endl;
#endif
    rep(i, 0, nSize-1) {
        if (arr[i].type == 0) {
            auto it = s.lower_bound(arr[i]);
            if (it == s.end()) {
                //cout << "break at idx: " << arr[i].idx << endl;
                ok = 0;
                break;
            } else {
                //cout << "give part " << arr[i].idx << " to " << it->idx << endl;
                ans[arr[i].idx] = it->idx;
                if ((--ki[it->idx]) == 0) s.erase(it);
            }
        } else {
            s.insert(arr[i]);
        }
        //cout << "set size: " << s.size() << endl;
    }
    if (ok) {
        cout << "YES\n";
        rep(i, 1, n-1) cout << ans[i] << ' ';cout << ans[n] << endl;
    }
    else
        cout << "NO\n";
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值