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 ;
}
posted @ 2021-09-13 21:09  wlhp  阅读(102)  评论(0)    收藏  举报