CSP第29次认证题解 2023.1

只有前400分!

A、田地丈量


样例输入1

4 10 10
0 0 5 5
5 -2 15 3
8 8 15 15
-2 10 3 15
44

#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
#define x1 asdawd
#define y1 hjhjkhf

template <class T>
inline void read(T& a){
    T x = 0, s = 1;
    char c = getchar();
    while(!isdigit(c)){ if(c == '-') s = -1; c = getchar();  }
    while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
    a = x * s;
    return ; 
}

int n; 
int a, b; 
int x1, y1, x2, y2; 

int main(){
    // freopen("hh.txt", "r", stdin); 
    read(n), read(a), read(b); 
    ll ans = 0; 
    for(int i = 1; i <= n; i++){
        cin >> x1 >> y1 >> x2 >> y2; 
        if(x2 < 0 || x1 > a || y2 < 0 || y1 > b) continue; 
        int mx1 = min(x2, a); 
        int my1 = min(y2, b); 
        int mx2 = max(0, x1); 
        int my2 = max(0, y1); 
        ans += (mx1 - mx2) * (my1 - my2); 
    }
    cout << ans << endl; 
    return 0; 
}

B、垦田计划


样例输入2

4 9 2
6 1
5 1
6 2
7 1
5

4 30 2
6 1
5 1
6 2
7 1
2

#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long

template <class T>
inline void read(T& a){
    T x = 0, s = 1;
    char c = getchar();
    while(!isdigit(c)){ if(c == '-') s = -1; c = getchar();  }
    while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
    a = x * s;
    return ; 
}

int n, m, k; 
int t[N], c[N]; 

bool check(int lim){
    int m1 = m; 
    for(int i = 1; i <= n; i++){
        if(k > lim) return 0; 
        if(t[i] > lim){
            int del = t[i] - lim; 
            m1 -= c[i] * del; 
        } 
    }
    return m1 >= 0; 
}

int main(){
    // freopen("hh.txt", "r", stdin); 
    read(n), read(m), read(k); 
    for(int i = 1; i <= n; i++){
        read(t[i]), read(c[i]); 
    }
    int l = 1, r = 1e9; 
    int ans = 0; 
    while(l <= r){
        int mid = l + r >> 1; 
        if(check(mid)) ans = mid, r = mid - 1; 
        else l = mid + 1; 
    }
    cout << ans << endl; 
    return 0; 
}

C、LDAP



测试样例3

2
1 2 1 2 2 3
2 2 2 3 3 1
4
1:2
3~1
&(1:2)(2:3)
|(1:2)(3:1)
1

1
1 2

#include <bits/stdc++.h>
using namespace std;
#define N 2500
#define ll long long

template <class T>
inline void read(T& a){
    T x = 0, s = 1;
    char c = getchar();
    while(!isdigit(c)){ if(c == '-') s = -1; c = getchar();  }
    while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
    a = x * s;
    return ; 
}

struct People{
    int DN;   //  题目中编号
    map <int, int> G; 
} p[N]; 

int n, m; 
set <int> ans; 

struct node{
    int op;  // 1表示 |, 2表示 &
    int lson, rson; 

    int left; int right; 
    int op1;  // 1表示 :, 2表示 ~ 

    void clean(){
        op = op1 = -1; 
        lson = 0, rson = 0; 
        left = 0, right = 0; 
        return ; 
    }

    void print(){
        printf("%d %d %d %d %d %d\n", op, lson, rson, op1, left, right); 
        return ; 
    }

    node(){
        op = -1; 
        op1 = -1; 
        return ; 
    }
} t[N]; 

int id = 0; 
int dfn = 0;  // 当前节点编号
string s; 
int root = 0; 

void clean(){ // 清空树
    for(int i = 0; i <= dfn; i++)
        t[i].clean(); 
    return ; 
}

void dfs(int &now){
    now = ++dfn;
    if(id >= s.length()) return ; 
    if(s[id] == '|' || s[id] == '&'){ // 这个点是逻辑符编号
        t[now].op = s[id] == '|' ? 1 : 2; 
        id += 2; // 越过左括号
        dfs(t[now].lson); 
        dfs(t[now].rson);  
    }
    else if(isdigit(s[id])){ // 表达式
        int tmp = 0; 
        while(isdigit(s[id])){
            tmp = tmp * 10 + (s[id] - '0'); 
            id++; 
        }
        t[now].left = tmp; 
        t[now].op1 = s[id] == ':' ? 1 : 2;  
        tmp = 0; 
        id++; 
        while(isdigit(s[id])){
            tmp = tmp * 10 + (s[id] - '0');
            id++; 
        }
        t[now].right = tmp; 
        while(s[id] == '(' || s[id] == ')') id++; 
        return ; 
    } 
    return ; 
}

int get_ans(int now, int pid){  // pid: 检查 pid 是否符合这一条的要求
    // printf("now: %d\n", now); 
    // t[now].print();     
    if(t[now].op != -1){  // 这一个点是逻辑符
        if(t[now].op == 1) return get_ans(t[now].lson, pid) | get_ans(t[now].rson, pid); 
        else return get_ans(t[now].lson, pid) & get_ans(t[now].rson, pid); 
    }
    else{  // 这一个节点是运算
        int left = t[now].left, right = t[now].right; 
        int op1 = t[now].op1; 
        bool flag = 0; 
        if(op1 == 1){
            if(p[pid].G.count(left) && p[pid].G[left] == right) flag = 1; 
        }
        else{
            if(p[pid].G.count(left) && p[pid].G[left] != right) flag = 1; 
        }
        return flag; 
    }
}

void check(){
    id = 0; // 第 0 位开始检查 s
    dfn = 0; 
    root = 0; 
    dfs(root);  // 建树
    for(int i = 1; i <= n; i++){
        int tmp = get_ans(root, i); 
        if(tmp) ans.insert(p[i].DN); 
    }
    return ; 
}

int main(){
    // freopen("hh.txt", "r", stdin); 
    read(n); 
    for(int i = 1; i <= n; i++){
        read(p[i].DN); 
        int num; read(num); 
        for(int j = 1; j <= num; j++){
            int x, y; 
            read(x), read(y); 
            p[i].G[x] = y;  
        }
    }
    read(m); 
    for(int i = 1; i <= m; i++){
        ans.clear(); 
        cin >> s; 
        clean(); 
        check(); 
        for(auto it : ans){
            printf("%d ", it); 
        }
        puts(""); 
    }
    return 0; 
}

D、星际网络II


样例输入1

32 12
1 1 0001:8000 0001:ffff
2 0001:a000
3 0001:c000 0001:ffff
1 2 0000:0000 000f:ffff
2 0000:1000
1 1 0001:8000 0001:8fff
1 2 0000:0000 0000:ffff
2 0000:1000
1 1 0002:8000 0002:ffff
3 0001:8000 0002:ffff
1 1 0001:c000 0003:ffff
3 0001:8000 0002:ffff

样例输出1

YES
1
1
NO
0
NO
YES
2
YES
0
YES
1

题解

先用字符串操作离散化,不需要管\(n\),直接排序即可。在离散化的时候,需要注意两个数字是否相邻,不然要在中间多插入一个,因为这道题涉及到判断是否“全部”占满。
然后就是线段树,一个变量用来记录刷子,一个记录是否只有一个颜色,当只有一个颜色的时候,再记录是哪一个颜色(非严格的,考虑了0的情况),然后一个记录是否全部刷满。

#include <bits/stdc++.h>
using namespace std;
#define N 200010
#define ll long long

template <class T>
inline void read(T& a){
    T x = 0, s = 1;
    char c = getchar(); 
    while(!isdigit(c)){ if(c == '-')  s = -1; c = getchar(); }
    while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
    a = x * s;
    return ; 
}

int n, m; 

struct node{
    string s1, s2; 
    int opt; 
    int id; 
} que[N]; 

set <string> G; 
map <string, int> g; 
int mn = 0; 

bool compar(string s1, string s2){ // s1 > s2
    // cout << s1 << "  "; 
    int p = s1.length() - 1; 
    while(p >= 0){
        if(s1[p] == ':'){
            p--; 
            continue; 
        }
        if(s1[p] == 'a'){
            s1[p] = '9'; 
            break; 
        } 
        if(s1[p] != '0'){
            s1[p]--; 
            break; 
        }
        s1[p] = 'f'; 
        p--; 
    }
    // cout << s1 << endl; 
    if(s1 == s2) return 1; 
    else return 0; 
}

unsigned ll po[N]; 
const unsigned ll base = 131;  

struct Segment_tree{
    struct node{
        int colnum; //这个区间是否只有一个颜色
        int col; //这个区间下面全是某个颜色或空
        int isFull; //这个区间满了没有
        int shua; 
    } t[N << 2];

    #define lson (o<<1)
    #define rson (o<<1|1)

    inline void pushup(int o){
        if(t[lson].colnum || t[rson].colnum || (t[lson].col != t[rson].col && t[lson].col != 0 && t[rson].col != 0)){
            t[o].colnum = 1; 
            t[o].col = 0; 
        }
        else{
            t[o].col = (t[lson].col == 0 ? t[rson].col : t[lson].col); 
        }
        t[o].isFull = t[lson].isFull & t[rson].isFull; 
        return ; 
    }

    inline void pushdown(int o){
        if(t[o].shua){
            t[lson].shua = t[rson].shua = t[o].shua; 
            t[lson].isFull = t[rson].isFull = t[o].isFull; 
            t[lson].colnum = t[rson].colnum = t[o].colnum; 
            t[lson].col = t[rson].col = t[o].shua; 
        }
        t[o].shua = 0; 
        return ; 
    }

    void update(int o, int l, int r, int in, int end, int k){
        if(l > end || r < in) return ; 
        if(l >= in && r <= end){
            t[o].col = k; 
            t[o].shua = k; 
            t[o].isFull = 1; 
            t[o].colnum = 0; 
            return ; 
        }
        pushdown(o); 
        int mid = l + r >> 1;
        update(lson, l, mid, in, end, k); 
        update(rson, mid + 1, r, in, end, k); 
        pushup(o); 
        return ; 
    }

    int query1(int o, int l, int r, int in, int end){ // 查询区间是否塞满
        if(l > end || r < in) return 1; 
        if(l >= in && r <= end){
            // printf("query1: l: %d r: %d FULL: %d\n", l, r, t[o].isFull);
            return t[o].isFull; 
        }
        int mid = l + r >> 1; 
        pushdown(o); 
        return query1(lson, l, mid, in, end) & query1(rson, mid + 1, r, in, end); 
    }

    int query2(int o, int l, int r, int in, int end, int k){ // 区间内是否只有 k 
        if(l > end || r < in) return 1;
        if(l >= in && r <= end){
            // printf(" query2: l: %d %d col: %d num: %d\n", l, r, t[o].col, t[o].colnum); 
            if(t[o].colnum) return 0; // 不止一个颜色
            if(t[o].col == 0 || t[o].col == k) return 1; 
            else{
                // puts("return wrong!"); 
                return 0; 
            } 
        } 
        int mid = l + r >> 1;
        pushdown(o); 
        return query2(lson, l, mid, in, end, k) & query2(rson, mid + 1, r, in, end, k); 
    }

    int query3(int o, int l, int r, int in, int end){
        if(l > end || r < in)return 0; 
        if(l >= in && r <= end) return t[o].col; 
        int mid = l + r >> 1;
        pushdown(o); 
        return query3(lson, l, mid, in, end) + query3(rson, mid + 1, r, in, end); 
    }


    int query5(int o, int l, int r, int in, int end){ // 塞满了之后,是否是同一个颜色
        if(l > end || r < in) return 0; 
        if(l >= in && r <= end){        
            if(t[o].colnum == 0) return t[o].col; 
            else return -1; 
        }
        int mid = l + r >> 1; 
        int tmp1 = query5(lson, l, mid, in, end); 
        int tmp2 = query5(rson, mid + 1, r, in, end); 
        if(tmp1 == -1 || tmp2 == -1) return -1; 
        else{
            if(tmp1 != tmp2 && tmp1 != 0 && tmp2 != 0) return -1; 
            else return tmp1 == 0 ? tmp2 : tmp1; 
        }
    }

} tree; 

int main(){
    //freopen("hh.txt", "r", stdin); 
    read(n), read(m); 
    for(int i = 1; i <= m; i++){
        read(que[i].opt); 
        if(que[i].opt == 1){
            read(que[i].id); 
            cin >> que[i].s1 >> que[i].s2; 
            G.insert(que[i].s1); 
            G.insert(que[i].s2); 
        }
        else if(que[i].opt == 2){
            cin >> que[i].s1; 
            G.insert(que[i].s1);  
        }
        else{
            cin >> que[i].s1 >> que[i].s2; 
            G.insert(que[i].s1); 
            G.insert(que[i].s2); 
        }
    }
    for(auto it = G.begin(); it != G.end(); it++){
        if(it == G.begin()){
            g[*it] = ++mn; 
            continue; 
        }
        else{
            auto it1 = it; 
            it1--; 
            bool flag = compar(*it, *it1); //大小是否相邻
            if(flag) g[*it] = ++mn; 
            else{
                mn += 2; 
                g[*it] = mn; 
            }
        }
    }

    for(int i = 1; i <= m; i++){
        if(que[i].opt == 1){
            int id = que[i].id; 
            int l = g[que[i].s1]; 
            int r = g[que[i].s2];  
            // printf("l r: %d %d\n", l, r); 
            bool flag = tree.query1(1, 1, mn, l, r); //先判断是否完全填满
            // printf("666flag: %d %d\n", flag, id); 
            if(flag == 1){
                puts("NO"); 
                continue; 
            }
            flag = (tree.query2(1, 1, mn, l, r, id) ^ 1); 
            // printf("6666flag: %d\n", flag); 
            if(flag == 0){
                puts("YES"); 
                tree.update(1, 1, mn, l, r, id); 
            }
            else puts("NO"); 
        }
        else if(que[i].opt == 2){
            cout << tree.query3(1, 1, mn, g[que[i].s1], g[que[i].s1]) << endl; 
        }
        else{
            int l = g[que[i].s1], r = g[que[i].s2]; 
            // printf("opt3: l r: %d %d\n", l, r); 
            bool flag = tree.query1(1, 1, mn, l, r); 
            if(flag){
                int ans = tree.query5(1, 1, mn, l, r); 
                // printf("ans: %d\n", ans); 
                if(ans == -1) puts("0"); 
                else cout << ans << endl; 
            }
            else puts("0"); 
        }
    }



    return 0;   
}   
posted @ 2023-03-27 21:06  雪之下,树之旁  阅读(151)  评论(0编辑  收藏  举报