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