省选测试11

省选测试 11

T1

题目链接

​ 排序 + 贪心.

​ 我们将\(a\)从大到小排序后可以得到 : \(a_1 \geq a_2 \geq \dots \geq a_n\).

​ 所以我们可以知道 : \(|a_2 - a_3| + |a_4 - a_5| + \dots + |a_{n-1} - a_n| < a_1\).(因为\(a_i \geq 1\))

​ 这个条件有什么用呢? 我们为了时选出的\(a\)合法, 那么就要\(suma(选) > suma(未选)\).

​ 我们要选出\(\frac{n}{2} +1\)个数, 我们考虑这么选 : 一定选\(a_1\), 其余的\(a_2, a_3\)选一个, \(a_4,a_5\)选一个 ...为什么这么选呢? 由上面那个条件可以知道, 这么选一定是 \(suma(选) > suma(未选)\) 的.

​ 所以我们贪心的在每个块里选\(b_i\)较大的就好了.

​ 但是还有个问题, 万一只有选两个相邻的\(b\)才能满足条件怎么办? 其实这种情况不会发生, 下面是证明 :

​ 比如说有 : \(b_1, b_2, b_3, b_4, b_5\).

​ 只有 : \(2*(b_1 +b_2 +b_3) > sumb\), 没有 : \(2*(b_1 + b_{2 | 3} +b_{4|5}) <= sumb\)

​ 那么我们可以得到 : \(b_1 + b_2 + b_3 > b_4 + b_5\), \(b_1 +b_2 + b_4 <= b_3 + b_5(2)\)

​ 既然我们按上面的方法选出了\(b_1, b_2, b_4\), 那么就说明 : \(b_2 >= b_3, b_4 >= b_5\)

​ 又由上面的\((2)\)式移项可以得到 : \(b_1 <= b_3 - b_2 + b_5 - b_4 < 0\).

​ 又因为\(b_1 > 0\), 所以不存在这种情况.

#include <bits/stdc++.h>

using namespace std;

inline long long read() {
    long long s = 0, f = 1; char ch;
    while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    return s * f;
}

const int N = 1e5 + 5;
int n, cnt;
long long suma, sumb, tmpa, tmpb;
struct node { int a, b, id; } x[N], tmp[N];

int cmp(node x, node y) {
    return x.a > y.a;
}

int mmp(node x, node y) {
    return x.a == y.a ? x.id < y.id : x.a > y.a;
}

int main() {

    // freopen("game.in","r",stdin); freopen("game.out","w",stdout);

    n = read();
    for(int i = 1;i <= n; i++) x[i].a = read(), suma += x[i].a;
    for(int i = 1;i <= n; i++) x[i].b = read(), sumb += x[i].b;
    for(int i = 1;i <= n; i++) x[i].id = i;
    sort(x + 1, x + n + 1, cmp);
    tmpa += x[1].a; tmpb += x[1].b; tmp[++ cnt] = x[1];
    for(int i = 2;i <= n; i += 2) {
        if(x[i].b >= x[i + 1].b) tmpb += x[i].b, tmpa += x[i].a, tmp[++ cnt] = x[i];
        else tmpb += x[i + 1].b, tmpa += x[i + 1].a, tmp[++ cnt] = x[i + 1];
    }
    if(tmpb * 2 <= sumb || tmpa * 2 <= suma) { printf("-1\n"); }
    else {
        printf("%d\n", cnt);
        sort(tmp + 1, tmp + cnt + 1, mmp);
        for(int i = 1;i <= cnt; i++) printf("%d ", tmp[i].id);
    }

    fclose(stdin); fclose(stdout);

    return 0;
}

T2

题目链接

​ 这道题一看还以为是个可持久化数据结构, 没想到乱搞搞就好了.

​ 发现题目要求的操作十分的简单, 只需维护一下01的个数就好了, 所以我们完全没必要去写可持久化.

​ 对于操作是1,2,3类型的, 我们直接往它的上一次操作连边, 对于操作是4类型的, 我们往它要返回的那一次操作连边, 这样就构成了一颗操作树, 我们直接在这颗操作树上\(dfs\)就可以了.

#include <bits/stdc++.h>

using namespace std;

inline long long read() {
    long long s = 0, f = 1; char ch;
    while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    return s * f;
}

const int M = 1e3 + 5, K = 1e5 + 5;
int n, m, q_, res, cnt;
int col[M][M], Col[M], num[M], ans[K], head[K];
struct ques { int opt, x, y, f; } q[K];
struct edge { int to, nxt; } e[K << 1];

void add(int x, int y) {
    // cout << x << " " << y << "!!!!\n";
    e[++ cnt].nxt = head[x]; head[x] = cnt; e[cnt].to = y;
}

void Work(int now, int f) {
    // cout << now << " " << f << "------->";
    if(f == 0) {
        if(q[now].opt == 2) {
            if(!Col[q[now].x]) {
                if(col[q[now].x][q[now].y]) {
                    num[q[now].x] --; res --; col[q[now].x][q[now].y] = 0;
                }
                else q[now].f = 1;
            }
            else {
                if(!col[q[now].x][q[now].y]) {
                    num[q[now].x] ++; res --; col[q[now].x][q[now].y] = 1;
                }
                else q[now].f = 1;
            }
        }
        if(q[now].opt == 1) {
            if(!Col[q[now].x]) {
                if(!col[q[now].x][q[now].y]) {
                    num[q[now].x] ++; res ++; col[q[now].x][q[now].y] = 1;
                }
                else q[now].f = 1;
            }
            else {
                if(col[q[now].x][q[now].y]) {
                    num[q[now].x] --; res ++; col[q[now].x][q[now].y] = 0;
                }
                else q[now].f = 1;
            }
        }
        if(q[now].opt == 3) {
            if(!Col[q[now].x]) res -= num[q[now].x], res += m - num[q[now].x];
            else res -= m - num[q[now].x], res += num[q[now].x];
            Col[q[now].x] ^= 1;
        }
    }
    else {
        if(q[now].opt == 2) {
            if(!Col[q[now].x]) {
                if(!q[now].f) {
                    num[q[now].x] ++; res ++; col[q[now].x][q[now].y] = 1;
                }
            }
            else {
                if(!q[now].f) {
                    num[q[now].x] --; res ++; col[q[now].x][q[now].y] = 0;
                }
            }
        }
        if(q[now].opt == 1) {
            if(!Col[q[now].x]) {
                if(!q[now].f) {
                    num[q[now].x] --; res --; col[q[now].x][q[now].y] = 0;
                }
            }
            else {
                if(!q[now].f) {
                    num[q[now].x] ++; res --; col[q[now].x][q[now].y] = 1;
                }
            }
        }
        if(q[now].opt == 3) {
            if(!Col[q[now].x]) res -= num[q[now].x], res += m - num[q[now].x];
            else res -= m - num[q[now].x], res += num[q[now].x];
            Col[q[now].x] ^= 1;
        }
    }
    // cout << res << "\n";
}

void dfs(int x) {
    // cout << x << "++++++\n";
    Work(x, 0); ans[x] = res;
    // cout << x << " " << ans[x] << " " << res << "+++\n";
    for(int i = head[x]; i ; i = e[i].nxt) dfs(e[i].to);
    Work(x, 1);
    // cout << x << " " << ans[x] << " " << res << "---\n";
}

int main() {

    // freopen("now.in","r",stdin); freopen("now.out","w",stdout);

    n = read(); m = read(); q_ = read();
    for(int i = 1;i <= q_; i++) {
        q[i].opt = read(); q[i].x = read();
        if(q[i].opt <= 2) q[i].y = read();
        if(q[i].opt == 4) {
            add(q[i].x, i);
        }
        else add(i - 1, i);
    }
    dfs(0);
    for(int i = 1;i <= q_; i++) printf("%d\n", ans[i]); 

    fclose(stdin); fclose(stdout);

    return 0;
}

/*
2 3 4 
1 1 1 
3 2 
4 0 
1 1 1

999 999 12
2 693 492
1 639 609
4 1
4 0
1 419 528
3 223
1 1 36
4 6
1 75 3
1 327 629
4 8
2 222 216
*/

T3

题目链接

​ 欧拉回路.

​ 由于一些区间是这样的 : \([x,x]\). 也就是只覆盖一个点, 我们不太好操作, 于是我们把点转化成线段, 那么每一个区间就变成了\([x,x+1]\)\([x,y+1]\)了, 这样比较舒服.

​ 我们把红色区间看成+1, 绿色区间看成-1, 最后我们需要每个点\(|\sum p_i| \leq 1\).

​ 不会了..............

#include <bits/stdc++.h>

using namespace std;

inline long long read() {
    long long s = 0, f = 1; char ch;
    while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    return s * f;
}

const int N = 2e5 + 5;
int n, cnt, cnt_b;
int b[N], c[N], s[N], t[N], vis[N], head[N], in_du[N], out_du[N];
struct line { int l, r; } L[N];
struct edge { int f, id, to, nxt; } e[N << 1];

void add(int x, int y, int i) {
    e[++ cnt].nxt = head[x]; head[x] = cnt; e[cnt].to = y; e[cnt].id = i;
}

void dfs(int x) {
    vis[x] = 1;
    for(int i = head[x]; i ; i = e[i].nxt) {
        int y = e[i].to; if(e[i].f) continue ;
        s[e[i].id] = x; t[e[i].id] = y;
        e[i].f = e[i ^ 1].f = 1;
        // cout << x << " " << y << "\n";
        dfs(y);
    }
}

int main() {

    // freopen("party.in","r",stdin); freopen("party.out","w",stdout);
    
    n = read(); cnt = 1;
    for(int i = 1;i <= n; i++) {
        L[i].l = read(), L[i].r = read() + 1; 
        b[++ cnt_b] = L[i].l, b[++ cnt_b] = L[i].r;
    }
    sort(b + 1, b + cnt_b + 1);
    cnt_b = unique(b + 1, b + cnt_b + 1) - b - 1;
    for(int i = 1;i <= n; i++) {
        L[i].l = lower_bound(b + 1, b + cnt_b + 1, L[i].l) - b;
        L[i].r = lower_bound(b + 1, b + cnt_b + 1, L[i].r) - b;
        add(L[i].l, L[i].r, i); add(L[i].r, L[i].l, i);
        out_du[L[i].l] ++; in_du[L[i].r] ++;
    }
    for(int i = 1;i <= cnt_b; i++) {
        c[i] = c[i - 1] + out_du[i] - in_du[i];
        if(c[i] & 1) 
            add(i, i + 1, n + 1), add(i + 1, i, n + 1);
    }
    for(int i = 1;i <= cnt_b; i++) if(!vis[i]) dfs(i);
    for(int i = 1;i <= n; i++) 
        printf("%d ", s[i] < t[i] ? 0 : 1);

    // fclose(stdin); fclose(stdout);

    return 0;
}

/*
2
0 2 
2 3

6
1 5 
1 3 
3 5 
2 10 
11 11 
12 12
*/
posted @ 2021-03-12 22:04  C锥  阅读(142)  评论(0编辑  收藏  举报