2019四川省赛——解题报告(A,B,G,H,I,J)

oj: 链接

2021/3/10 训练赛

A. Autochess

oj: 链接

题解

题意有点难懂,不过还能理解,而且还有点坑。
读懂题后,发现最难维护的点在于怎么快速找到最左边空着的位置。
我们的做法是二分+树状数组维护,同时用 m a p map map维护每个字符串的所有位置
树状数组维护非空位置的个数,这样就可以二分出最左边空着的位置,
然后再根据当前插入的字符串模拟并维护 m a p map map和树状数组即可。
其实想法不是特别难,不过题意有点坑,(所幸队友没被坑到。。)

代码

#include <bits/stdc++.h>
#define m_p make_pair
#define _for(i, a) for(int i = 0, len = (a); i < len; ++i)
#define _rep(i, a, b) for(int i = (a), len = (b); i <= len; ++i)
#define outval(a) cout << "debuging|" << #a << ":" << a << "\n";
#define dg if(debug)
#define sc(x) scanf("%d", &x)
#define scl(x) scanf("%lld", &x)
#define mem0(x) memset(x, 0, sizeof(x))
#define lowbit(x) (x & (-x))
using namespace std;
int debug = 0;
const int maxn = 100005;
const int inf = 0x3f3f3f3f;
typedef long long LL;

inline LL read() {
   
    LL x(0), f(1); char c(getchar());
    while(c < '0' || c > '9') {
   
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
   
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x * f;
}

struct poi{
   

};

int n, m, k;
string s;
map< string, vector<int> > mp;
vector<string> ans;

int dat[maxn];
void insert(int p, int x) {
   
    while(p <= m) {
   
        dat[p] += x;
        p += lowbit(p);
    }
}
int query(int p) {
   
    int ans = 0;
    while(p) {
   
        ans += dat[p];
        p -= lowbit(p);
    }
    return ans;
}

int leftmost() {
   
    int l = 1, r = m, ans = m + 1;
    while(l <= r) {
   
        int mid = (l + r) >> 1;
        int tem = query(mid);
        if(query(mid) < mid) {
   
            ans = mid;
            r = mid - 1;
        }
        else l = mid + 1;
    }
    return ans;
}

void init() {
   
    mem0(dat);
    mp.clear();
    ans.resize(m + 1);
    _rep(i, 1, m) ans[i] = "";
    _rep(i, 1, m) dat[i] = 0;
}

int sol(int ttt) {
   
    init();
    int np = 0;
    _rep(i, 1, n) {
   
        string s;
        cin >> s;
        if(mp.count(s + "3")) continue;
        if((mp[s].size() + 1) % k && np == m) continue;
        int t = leftmost();
        // if(t > m) continue;
        insert(t, 1);
        mp[s].push_back(t);
        ++np;
        if(mp[s].size() == k) {
   
            dg {
   
                cout << "s:" << s << "\tpos:";
                for(auto i : mp[s]) cout << " " << i;
                cout << "\n";
            }
            for(int i : mp[s]) insert(i, -1);
            mp.erase(mp.find(s));
            np -= k - 1;
            int t = leftmost();
            insert(t, 1);
            s.push_back('2');
            mp[s].push_back(t);
            if(mp[s].size() == k) {
   
                for(int i : mp[s]) insert(i, -1);
                mp.erase(mp.find(s));
                np -= k - 1;
                s[s.size() - 1] = '3';
                int t = leftmost();
                insert(t, 1);
                mp[s].push_back(t);
            }
        }
    }
    cout << "Case " << ttt << ":";
    for(auto i : mp) {
   
        for(int j : i.second) {
   
            ans[j] = i.first;
        }
    }
    _rep(i, 1, m) {
   
        if(ans[i].size() != 0) {
   
            cout << " " << ans[i];
        }
        else cout << " -1";
    }
    cout << "\n";
    return 0;
}

int main() {
   
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    // debug = 1;
#endif
    int T;
    cin >> T;
    _for(i, T) {
   
        cin >> n >> m >> k;
        sol(i + 1);
    }
    return 0;
}

B. Bin Packing

oj: 链接

题解

直接暴力枚举四种情况维护答案即可。
1.两个都竖着
2.两个都横着
3.一个横着一个竖着(两种情况)

代码

#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define pY puts("YES")
#define pN puts("NO")
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
#define outval2(a,b) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b << "\n";
#define outval3(a,b,c) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b <<"\t"<< #c << ": " << c << "\n";
using namespace std;
int debug = 0;
ll 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值