2019 icpc 香港
E题:思维题
10000的数据可以\(n^2\) 做,那么可以枚举判断每个数,对于每个数,比它大的置1,比它小的置0,那么0和1的个数相同显然可以,如果01个数不同,可以发现三个连起来的0或者1可以变成1个,那么对于多出来的,判断可不可以通过连续三个这样的消到和少的一样多就可以了。判断连续三个贪心来做即可。
const int maxn = 1e5 + 10;
int a[maxn], n;
char s[maxn], s2[maxn];
int get(int i, char c) {
int cnt = 0, sz = 0;
for(int j = 1; j < i; ++ j) {
if(s2[j] == c) cnt ++;
else {
cnt --;
if(cnt < 0) cnt = 0;
}
if(cnt == 3) cnt = 1, sz ++;
}
cnt = 0;
for(int j = i + 1; j <= n; ++ j) {
if(s2[j] == c) cnt ++;
else {
cnt --;
if(cnt < 0) cnt = 0;
}
if(cnt == 3) cnt = 1, sz ++;
}
return sz;
}
void run() {
cin >> n;
for(int i = 1; i <= n; ++ i) cin >> a[i];
for(int i = 1; i <= n; ++ i) {
s[i] = '0';
int lz = 0, rz = 0, lo = 0, ro = 0;
for(int j = 1; j < i; ++ j) a[j] > a[i] ? (lo ++, s2[j] = '1') : (lz ++, s2[j] = '0');
for(int j = i + 1; j <= n; ++ j) a[j] > a[i] ? (ro ++, s2[j] = '1') : (rz ++, s2[j] = '0');
if(lo + ro == lz + rz) s[i] = '1';
else if(lo + ro < lz + rz) {
int sz = get(i, '0');
if(lo + ro + 2 * sz >= lz + rz) s[i] = '1';
}
else {
int sz = get(i, '1');
if(rz + lz + sz * 2 >= lo + ro) s[i] = '1';
}
}
s[n + 1] = '\0';
cout << s + 1 << '\n';
return ;
}
G:思维题
做法很多,一个思路就是开根号,\(1e9\)开根号得到\(3e4\),一个分支个数是\(sqrt\),另外一个是\(n / sqrt\),上面是连续的\(n - sqrt * (n / sqrt)\)个,总数就是\(sqrt + n / sqrt + n - sqrt * (n / sqrt)\) 差不多等于 \(3 * sqrt\)
I: 思维题
考虑如何减少检查次数,一开始可以对每个询问的观测点都放入\(\frac 1 k\)的目标,那么当这个观测点满足了\(\frac 1 k\),再拿出来更新重新放入现在的\(\frac 1 k\)的目标,这样每次至少减去\(\frac 1 k\),可以在\(log\)内减完,另外对每个观测点的目标可以用小顶堆维护。复杂度是\(n{log}^2\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7;
int a[maxn];
bool vis[maxn];
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>> > q[maxn];
struct node{
int x, k, a1, a2, a3, pre;
}qr[maxn];
void run() {
int n, m, pre = 0; cin >> n >> m;
int op, x, y, a1, a2, a3, cnt = 0, now;
vector<int> v;
for(int i = 1; i <= m; ++ i) {
cin >> op >> x >> y;
if(op == 1) {
cnt ++; x ^= pre; now = 0;
if(y == 1) {
cin >> a1; a1 ^= pre;
now += a[a1];
q[a1].push({x + a[a1], cnt});
}
else if(y == 2) {
cin >> a1 >> a2; a1 ^= pre; a2 ^= pre;
now += a[a1] + a[a2];
q[a1].push({a[a1] + x / 2, cnt});
q[a2].push({a[a2] + x / 2, cnt});
}
else {
cin >> a1 >> a2 >> a3;
a1 ^= pre; a2 ^= pre; a3 ^= pre;
now += a[a1] + a[a2] + a[a3];
q[a1].push({a[a1] + x / 3, cnt});
q[a2].push({a[a2] + x / 3, cnt});
q[a3].push({a[a3] + x / 3, cnt});
}
qr[cnt].x = x; qr[cnt].k = y; qr[cnt].pre = now;
qr[cnt].a1 = a1; qr[cnt].a2 = a2; qr[cnt].a3 = a3;
}
else {
x ^= pre; y ^= pre;
a[x] += y;
while(!q[x].empty()) {
pair<int, int> top = q[x].top();
if(vis[top.second] == 1) {
q[x].pop(); continue;
}
if(top.first > a[x]) break;
q[x].pop();
int id = top.second;
int tmp = -qr[id].pre + a[qr[id].a1];
if(qr[id].k > 1) tmp += a[qr[id].a2];
if(qr[id].k > 2) tmp += a[qr[id].a3];
if(tmp >= qr[id].x) {
v.push_back(id); vis[id] = 1;
}
else {
qr[id].x -= tmp;
qr[id].pre = qr[id].pre + tmp;
if(qr[id].k == 2)
q[qr[id].a2].push({a[qr[id].a2] + (qr[id].x + 1) / 2, id}),
q[qr[id].a1].push({a[qr[id].a1] + (qr[id].x + 1) / 2, id});
else
q[qr[id].a2].push({a[qr[id].a2] + (qr[id].x + 2) / 3, id}),
q[qr[id].a1].push({a[qr[id].a1] + (qr[id].x + 2) / 3, id}),
q[qr[id].a3].push({a[qr[id].a3] + (qr[id].x + 2) / 3, id});
}
}
cout << v.size();
pre = v.size();
sort(v.begin(), v.end());
for(auto it : v) cout << ' ' << it;
cout << '\n';
v.clear();
}
}
return ;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
int t = 1;
//cin >> t;
while(t--)
run();
return 0;
}
J:数位dp
\(dp[pos][presum][del]\),\(presum\)是前面位数的和,\(del\)是\(fx - x\)的差值
然后套上数位dp就行了
int dp[maxn][62][62], m, f[maxn];
char l[maxn], r[maxn];
int dfs(int pos, int pre, int del, char *s, bool limit) {
if(pos == -1) return (del == 0 ? 1 : 0);
if(!limit && ~dp[pos][pre][del]) return dp[pos][pre][del];
int up = limit ? (s[pos] - '0') : 9; ll ans = 0;
for(int i = 0; i <= up; ++ i)
ans += dfs(pos - 1, (pre + i) % m, (del + pre * i % m - i * f[pos] % m + m) % m, s, limit && i == up);
ans %= mod;
return limit ? ans : dp[pos][pre][del] = ans;
}
int check(char *s, int len) {
int ans1 = 0, ans2 = 0;
for(int i = len - 1; i >= 0; -- i) {
ans1 = (ans1 * 10 + (s[i] - '0')) % m;
for(int j = i - 1; j >= 0; -- j)
ans2 = (ans2 + (s[i] - '0') * (s[j] - '0')) % m;
}
if(ans1 == ans2) return 1;
else return 0;
}
void run() {
cin >> l >> r >> m;
int rlen = strlen(r), llen = strlen(l);
for(int i = 0; i <= rlen; ++ i)
for(int j = 0; j <= m; ++ j)
for(int k = 0; k <= m; ++ k)
dp[i][j][k] = -1;
f[0] = 1;
for(int i = 1; i <= rlen; ++ i) f[i] = f[i - 1] * 10 % m;
reverse(r, r + rlen);
reverse(l, l + llen);
cout << (dfs(rlen - 1, 0, 0, r, 1) - dfs(llen - 1, 0, 0, l, 1) + check(l, llen) + mod) % mod << '\n';
return ;
}

浙公网安备 33010602011771号