CSP-S模拟17

A. 最大匹配

这都可以排序……关于我把它画到了平面直角坐标系上怎么都想不出来这件事……

code
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2e5 + 3;
const ll mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

int n;
ll ans;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

struct node 
{
    int a, b;
    bool operator < (const node &T) const 
    {
        return a+b > T.a+T.b;
    }
}p[maxn];

int main()
{
    n = read();
    for(int i=1; i<=2*n; i++)
    {
        p[i].a = read(); p[i].b = read();
        if(p[i].a < p[i].b) swap(p[i].a, p[i].b);
    }
    sort(p+1, p+1+2*n);
    for(int i=1,j=2*n; i<=n; i++,j--)
    {
        ans += abs((ll)p[j].b-p[i].a);
    }
    printf("%lld\n", ans);
    
    return 0;
}

 

B. 挑战ABC

先特判不用操作的情况。

只需要一次操作的条件是,只有一种字符小于n,假设它是A,如果可以找到一个区间[l,r]把它变成A之后B的个数和C的个数都恰好为n就可以。

剩下的都可以用两次操作解决,构造方法是找到一个最小的位置p,使[1,p]中出现最多的字符恰好出现了n次,假设为A,还需要n-cntb[1,p]个B就把之后的这一段变成B,最后一段变成C。

code
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1e6 + 3;

int n, m, c[3][maxn], p;
char pc, s[maxn];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

bool f1(char t)
{
    int x = (t-'A'+1)%3, y = (t-'A'+2)%3;
    for(int l=1,r=1; l<=m; l++)
    {
        if(r < l) r = l;
        while((c[x][r]-c[x][l-1] < c[x][m]-n || c[y][r]-c[y][l-1] < c[y][m]-n) && r <= m) r++;
        if(c[x][r]-c[x][l-1] == c[x][m]-n && c[y][r]-c[y][l-1] == c[y][m]-n)
        {
            printf("1\n%d %d %c\n", l, r, t); return 1;
        }
    }
    return 0;
}

void f2()
{
    printf("2\n");
    int x = (pc-'A'+1)%3, y = (pc-'A'+2)%3;
    char X = x + 'A', Y = y + 'A';
    printf("%d %d %c\n", p+1, p+n-c[x][p], X);
    printf("%d %d %c\n", p+n-c[x][p]+1, m, Y);
}

int main()
{
    n = read(); m = n*3;
    scanf("%s", s+1);
    for(int i=1; i<=m; i++)
    {
        for(int j=0; j<3; j++) 
        {
            c[j][i] = c[j][i-1]; 
        }
        c[s[i]-'A'][i]++;
        if(!p && c[s[i]-'A'][i] == n) p = i, pc = s[i];
    }
    if(c[0][m] == c[1][m] && c[1][m] == c[2][m])
    {
        printf("0\n"); exit(0);
    }
    if(f1('A') || f1('B') || f1('C')) exit(0);
    f2();
    
    return 0;
}

 

C. 三级跳

原题是JOI open 2019,可以在LOJ 3153找到(我好像刚才不小心写成了3193**),同时还来自上一届省选模拟31(3.14),T2法阵。

枚举前两个数,符合要求的前两个数中间不能有比这两个数大的数,如果有的话,这个数比原来的那两个优秀,用vector记录一下这些数对,然后用线段树维护原数组的区间最大值和实时更新的最大答案。

有效的(x, y)必然在从左到右单调栈时相遇(y弹掉x或y压在x的后面),这样的(x, y)只有O(n)对。

如果有的起点和中转点对应的最小的最后一个点大于n,就导致线段树更新时L > R。我本来以为多更新了不存在的答案至少应该变多,但是它变少了(样例1的第2个询问输出8本来是9),因为对于一个不合法的区间,L <= l && r <= R永远不可能满足条件即使是叶子,所以这个叶子就会被它不存在的孩子pushup,然后他的mx就变成了0!!!

code
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 5e5 + 3;

int n, a[maxn], Q, stk[maxn], top;
ll ans[maxn];
vector<int> vec[maxn];

struct que 
{
    int l, r, id;
    bool operator < (const que &T) const 
    {
        return l < T.l;
    }
}q[maxn];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

struct tree 
{
    struct node 
    {
        ll mx, ms, tag;
    }t[maxn<<2];
    void pushup(int x)
    {
        t[x].mx = max(t[x<<1].mx, t[x<<1|1].mx);
        t[x].ms = max(t[x<<1].ms, t[x<<1|1].ms);
    }
    void pushdown(int x)
    {
        int ls = x << 1, rs = x << 1 | 1;
        t[ls].ms = max(t[ls].ms, t[ls].mx+t[x].tag);
        t[ls].tag = max(t[ls].tag, t[x].tag);
        t[rs].ms = max(t[rs].ms, t[rs].mx+t[x].tag);
        t[rs].tag = max(t[rs].tag, t[x].tag);
        t[x].tag = 0;
    }
    void build(int x, int l, int r)
    {
        if(l == r)
        {
            t[x].ms = t[x].mx = a[l]; return;
        }
        int mid = (l + r) >> 1;
        build(x<<1, l, mid);
        build(x<<1|1, mid+1, r);
        pushup(x);
    }
    void update(int x, int l, int r, int L, int R, ll val)
    {
        if(L > R) return;
        if(L <= l && r <= R)
        {
            t[x].ms = max(t[x].ms, t[x].mx+val);
            t[x].tag = max(t[x].tag, val);
            return;
        }
        int mid = (l + r) >> 1;
        if(t[x].tag) pushdown(x);
        if(L <= mid) update(x<<1, l, mid, L, R, val);
        if(R > mid) update(x<<1|1, mid+1, r, L, R, val);
        pushup(x);
    }
    ll query(int x, int l, int r, int L, int R)
    {
        if(L <= l && r <= R) return t[x].ms;
        int mid = (l + r) >> 1; ll ans = 0;
        if(t[x].tag) pushdown(x);
        if(L <= mid) ans = max(ans, query(x<<1, l, mid, L, R));
        if(R > mid) ans = max(ans, query(x<<1|1, mid+1, r, L, R));
        return ans;
    }
}t;

int main()
{
    n = read();
    for(int i=1; i<=n; i++)
    {
        a[i] = read();
        while(top && a[stk[top]] <= a[i])
        {
            vec[stk[top]].push_back(i); top--;
        }
        if(top) vec[stk[top]].push_back(i);
        stk[++top] = i;
    }
    t.build(1, 1, n);
    Q = read();
    for(int i=1; i<=Q; i++)
    {
        q[i].l = read(); q[i].r = read(); q[i].id = i;
    }
    sort(q+1, q+1+Q); q[Q+1].l = n+1;
    for(int i=Q; i>=1; i--)
    {
        if(q[i].l < q[i+1].l)
        {
            for(int j=q[i+1].l-1; j>=q[i].l; j--)
            {
                for(int k : vec[j])
                {
                    t.update(1, 1, n, k-j+k, n, a[j]+a[k]);
                }
            }
        }
        ans[q[i].id] = t.query(1, 1, n, q[i].l, q[i].r);
    }
    for(int i=1; i<=Q; i++)
    {
        printf("%lld\n", ans[i]);
    }
    
    return 0;
}

 

D. 经典线性基

(⊙o⊙)…

posted @ 2022-10-07 18:59  Catherine_leah  阅读(63)  评论(0编辑  收藏  举报
/* */