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;
}