Codeforces Round #546 (Div. 2) ABCDE 题解
codeforces 1136A:
题意:一本书有n个章节,每个章节的分别在li到ri页,小明读完书后将书折在第k页,问还有多少章节没有读
题解:控制k在li~ri的范围内后输出n-i即可
#include <set> #include <map> #include <deque> #include <queue> #include <stack> #include <cmath> #include <ctime> #include <bitset> #include <cstdio> #include <string> #include <vector> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; typedef pair<LL, LL> pLL; typedef pair<LL, int> pLi; typedef pair<int, LL> pil;; typedef pair<int, int> pii; typedef unsigned long long uLL; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define bug printf("*********\n") #define FIN freopen("input.txt","r",stdin); #define FON freopen("output.txt","w+",stdout); #define IO ios::sync_with_stdio(false),cin.tie(0) #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n" #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n" #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n" LL 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 * 10 + ch - '0'; ch = getchar(); } return x * f; } const double eps = 1e-8; const int mod = 1e9 + 7; const int maxn = 2e5 + 5; const int INF = 0x3f3f3f3f; const LL INFLL = 0x3f3f3f3f3f3f3f3f; int l[maxn]; int r[maxn]; int main() { #ifndef ONLINE_JUDGE FIN #endif int n, k; scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%d%d", &l[i], &r[i]); } scanf("%d", &k); for(int i = 0; i < n; i++) { if(l[i] <= k && k <= r[i]) { cout << n - i << endl; return 0; } } return 0; }
codeforces 1136B:
题意:有n个井盖,井盖上有一颗石头,你每次可以做以下三种操作中的一种
1.将石头丢在隔壁的井盖上
2.走向相邻的井盖
3.如果井盖上没有石头,将井盖打开
你初始时在第k个井盖上,问你最少需要多少次操作可以打开全部的井盖
题解:每个井盖都需要进行3次操作才能到这个井盖上,首先我们需要到这个井盖上,然后我们需要搬石头,再然后我们要打开井盖,但是我们会走重复的路径,所以要想操作数最少,我们应该走重复的路最少,即min(n-k,k-1)
#include <set> #include <map> #include <deque> #include <queue> #include <stack> #include <cmath> #include <ctime> #include <bitset> #include <cstdio> #include <string> #include <vector> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; typedef pair<LL, LL> pLL; typedef pair<LL, int> pLi; typedef pair<int, LL> pil;; typedef pair<int, int> pii; typedef unsigned long long uLL; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define bug printf("*********\n") #define FIN freopen("input.txt","r",stdin); #define FON freopen("output.txt","w+",stdout); #define IO ios::sync_with_stdio(false),cin.tie(0) #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n" #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n" #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n" LL 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 * 10 + ch - '0'; ch = getchar(); } return x * f; } const double eps = 1e-8; const int mod = 1e9 + 7; const int maxn = 2e5 + 5; const int INF = 0x3f3f3f3f; const LL INFLL = 0x3f3f3f3f3f3f3f3f; int main() { #ifndef ONLINE_JUDGE FIN #endif int n,k; scanf("%d%d", &n, &k); cout << min(k - 1, n - k) + 3 * n << endl; return 0; }
codeforces 1136C:
题意:给你一个矩阵A和一个矩阵B,问你矩阵A和矩阵B是否是同类矩阵(转置矩阵也是同类的
题解:记录一下两个矩阵对角线上的元素是否相等即可
#include <set> #include <map> #include <deque> #include <queue> #include <stack> #include <cmath> #include <ctime> #include <bitset> #include <cstdio> #include <string> #include <vector> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; typedef pair<LL, LL> pLL; typedef pair<LL, int> pLi; typedef pair<int, LL> pil;; typedef pair<int, int> pii; typedef unsigned long long uLL; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define bug printf("*********\n") #define FIN freopen("input.txt","r",stdin); #define FON freopen("output.txt","w+",stdout); #define IO ios::sync_with_stdio(false),cin.tie(0) #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n" #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n" #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n" LL 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 * 10 + ch - '0'; ch = getchar(); } return x * f; } const double eps = 1e-8; const int mod = 1e9 + 7; const int maxn = 2e5 + 5; const int INF = 0x3f3f3f3f; const LL INFLL = 0x3f3f3f3f3f3f3f3f; int a[505][505]; int b[505][505]; vector<int> vec1[1005], vec2[1005]; int main() { #ifndef ONLINE_JUDGE FIN #endif int n, m; scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { scanf("%d", &a[i][j]); } } for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { scanf("%d", &b[i][j]); } } for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { vec1[i + j].push_back(a[i][j]); vec2[i + j].push_back(b[i][j]); } } for(int i = 0; i < n + m - 1; i++) { sort(vec1[i].begin(), vec1[i].end()); sort(vec2[i].begin(), vec2[i].end()); if(vec1[i] != vec2[i]) { cout << "NO" << endl; return 0; } } cout << "YES" << endl; return 0; }
codeforces 1136D:
题意:有一队人,其中有n对人可以两两交换,你在队伍的尾部,问你你最多可以向前移动多少步
题解:用一个vector记录你可以交换的人,然后判断你是否能与vector里面的人进行交换,如果你可以与vector里面所有的人交换的话,你就可以移动一步
#include <set> #include <map> #include <deque> #include <queue> #include <stack> #include <cmath> #include <ctime> #include <bitset> #include <cstdio> #include <string> #include <vector> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; typedef pair<LL, LL> pLL; typedef pair<LL, int> pLi; typedef pair<int, LL> pil;; typedef pair<int, int> pii; typedef unsigned long long uLL; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define bug printf("*********\n") #define FIN freopen("input.txt","r",stdin); #define FON freopen("output.txt","w+",stdout); #define IO ios::sync_with_stdio(false),cin.tie(0) #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n" #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n" #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n" LL 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 * 10 + ch - '0'; ch = getchar(); } return x * f; } const double eps = 1e-8; const int mod = 1e9 + 7; const int maxn = 2e6 + 5; const int INF = 0x3f3f3f3f; const LL INFLL = 0x3f3f3f3f3f3f3f3f; set<pair<int, int> > s; int a[maxn]; vector<int> vec; int main() { #ifndef ONLINE_JUDGE FIN #endif int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); } vec.push_back(a[n]); for(int i = 0, u, v; i < m; i++) { scanf("%d%d", &u, &v); s.insert(make_pair(u, v)); } int ans = 0; for(int i = n - 1; i >= 1; i--) { int flag = 1; for(int j = 0; j < vec.size(); j++) { if(s.count(make_pair(a[i], vec[j])) == 0) { flag = 0; break; } } if(flag) { ans++; } else { vec.push_back(a[i]); } } cout << ans << endl; return 0; }
codeforces 1136E:
题意:给你一个长度为n的序列a和长度为n-1的序列k,序列a在任何时候都满足如下性质,a[i+1]>=ai+ki,如果更新后a[i+1]<ai+ki了,那么a[i+1]=ai+ki
现在给你q次操作
操作1:将位置为pos的元素+x
操作2:询问区间l,r的区间和
题解:非常明显的线段树题,我们不好维护的是,如果更新后,当前数字变大到不满足限制条件时,我后面的元素也要做出相应的更新
那么我们就将a序列先减去k序列,这样的a序列也是满足限制条件了,然后我们记录下k的前缀和的前缀和,避免询问时缺少k的贡献,
数学推导如下
序列a满足单调不减性,
则∑ai 同样满足单调不减性,
当我们对位置为pos的元素进行更新时,
如果后面的元素 a[pos+R]<a[pos],则该元素要被覆盖,
所以我们二分右端点,将区间【pos,R】覆盖为a[pos]+x即可
为了避免重复计算ki对a的贡献所以我们覆盖区间时可以用如下技巧
用c来记录k的前缀和的前缀和
每次覆盖时,我们将区间【l,r】覆盖为(a[pos]+x-k[pos])*(r-l+1)+c[r+1]-c[l]
这样就不会使得k的贡献计算错了
#include <set> #include <map> #include <deque> #include <queue> #include <stack> #include <cmath> #include <ctime> #include <bitset> #include <cstdio> #include <string> #include <vector> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; typedef pair<LL, LL> pLL; typedef pair<LL, int> pLi; typedef pair<int, LL> pil;; typedef pair<int, int> pii; typedef unsigned long long uLL; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define bug printf("*********\n") #define FIN freopen("input.txt","r",stdin); #define FON freopen("output.txt","w+",stdout); #define IO ios::sync_with_stdio(false),cin.tie(0) #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n" #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n" #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n" LL 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 * 10 + ch - '0'; ch = getchar(); } return x * f; } const int maxn = 2e5 + 5; LL sum[maxn << 2]; LL lazy[maxn << 2]; LL a[maxn]; LL k[maxn]; LL sub[maxn]; LL c[maxn]; LL NUL = -1e18; void push_up(int rt) { sum[rt] = (LL)sum[rt << 1] + sum[rt << 1 | 1]; } void push_down(int l, int r, int rt) { if(lazy[rt] == NUL) return; int mid = (l + r) >> 1; lazy[rt << 1] = lazy[rt]; lazy[rt << 1 | 1] = lazy[rt]; sum[rt << 1] = (LL)(mid - l + 1) * lazy[rt] + c[mid + 1] - c[l]; sum[rt << 1 | 1] = (LL)(r - mid) * lazy[rt] + c[r + 1] - c[mid + 1]; lazy[rt] = NUL; } void build(int l, int r, int rt) { lazy[rt] = NUL; if(l == r) { sum[rt] = a[l]; return; } int mid = (l + r) >> 1; build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1); push_up(rt); } void update(int L, int R, LL val, int l, int r, int rt) { if(L <= l && r <= R) { sum[rt] = (LL)(r - l + 1) * val + c[r + 1] - c[l]; lazy[rt] = val; return; } int mid = (l + r) >> 1; push_down(l, r, rt); if(L <= mid) update(L, R, val, l, mid, rt << 1); if(R > mid) update(L, R, val, mid + 1, r, rt << 1 | 1); push_up(rt); } LL query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { //debug2(rt,sum[rt]); return sum[rt]; } int mid = (l + r) >> 1; push_down(l, r, rt); LL ans = 0; if(L <= mid) ans += query(L, R, l, mid, rt << 1); if(R > mid) ans += query(L, R, mid + 1, r, rt << 1 | 1); return ans; } int main() { #ifndef ONLINE_JUDGE FIN #endif int n; scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%lld", &a[i]); } for(int i = 1; i < n; i++) { scanf("%lld", &k[i]); k[i] = k[i] + k[i - 1]; } for(int i = 1; i <= n; i++) { c[i] = c[i - 1] + k[i - 1]; } build(0, n - 1, 1); int q; cin >> q; while(q--) { char op[2]; int l, r, pos; LL val; cin >> op; if(op[0] == '+') { cin >> pos >> val; pos--; int l = pos; int r = n - 1; LL tmp = query(pos, pos, 0, n - 1, 1); while(l < r) { int mid = (l + r + 1) / 2; if(tmp + val + k[mid] - k[pos] > query(mid, mid, 0, n - 1, 1)) { l = mid; } else { r = mid - 1; } } // debug3(pos, r, tmp + val - k[pos]); update(pos, r, tmp + val - k[pos], 0, n - 1, 1); } else { cin >> l >> r; cout << query(l - 1, r - 1, 0, n - 1, 1) << endl;; // printf("%lld\n", query(l - 1, r - 1, 0, n - 1, 1)); } } }