2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2018) Solution
A. Numbers
Unsolved.
B. Broken Watch
Solved.
题意:
一个圆盘上,有等分的n块区域,有三根指针,当三根指针分别位于两块区域的交界处时
指针的三点相连会形成一个三角形,求有多少个三角包含三指针的起点(即交汇处)
思路:
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef unsigned long long ull; 6 typedef long long ll; 7 8 ll A, B, C, n; 9 10 int main() 11 { 12 while(~scanf("%lld %lld %lld %lld" ,&A, &B, &C, &n)) 13 { 14 ull tmp = (n + 1) / 2; 15 tmp -= 2; 16 ull a = n, b = n - 1, c = n - 2; 17 if(a % 2 == 0) a /= 2; 18 else if(b % 2 == 0) b /= 2; 19 else if(c % 2 == 0) c /= 2; 20 21 if(a % 3 == 0) a /= 3; 22 else if(b % 3 == 0) b /= 3; 23 else if(c % 3 == 0) c /= 3; 24 25 ull ans = a * b * c; 26 27 ans -= n * (tmp * (tmp + 1) / 2); 28 29 if(A != B && B != C && C != A) ans = ans * 6; 30 else if(A != B || B != C || C != A) ans = ans * 3; 31 32 printf("%llu\n", ans); 33 } 34 return 0; 35 }
C. Tree
Solved.
题意:
一棵树中,有些点是黑点,有些点是白点,求恰选择m个黑点
使得黑点中任意两点的最长距离最短
思路:
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 110; 6 7 struct Edge{ 8 int to, nxt; 9 Edge(){} 10 Edge(int to, int nxt): to(to), nxt(nxt){} 11 }edge[maxn << 1]; 12 13 int n, m; 14 int p[maxn]; 15 int vis[maxn]; 16 int head[maxn], tot; 17 18 void Init(int n) 19 { 20 tot = 0; 21 for(int i = 1; i <= n; ++i) head[i] = -1; 22 } 23 24 void addedge(int u,int v) 25 { 26 edge[tot] = Edge(v, head[u]); head[u] = tot++; 27 edge[tot] = Edge(u, head[v]); head[v] = tot++; 28 } 29 30 int DFS(int u,int fa, int limit, int dis) 31 { 32 int res = p[u]; 33 if(dis == limit) return res; 34 for(int i = head[u]; ~i; i = edge[i].nxt) 35 { 36 int v = edge[i].to; 37 if(!vis[v] || v == fa) continue; 38 res += DFS(v, u, limit, dis + 1); 39 } 40 return res; 41 } 42 43 bool check(int mid) 44 { 45 for(int i = 1; i <= n; ++i) vis[i] = 0; 46 queue<int>q; 47 q.push(1); 48 while(!q.empty()) 49 { 50 int u = q.front(); 51 q.pop(); 52 vis[u] = 1; 53 if(DFS(u, -1, mid, 0) >= m) return true; 54 for(int i = head[u]; ~i; i = edge[i].nxt) 55 { 56 int v = edge[i].to; 57 if(vis[v]) continue; 58 q.push(v); 59 } 60 } 61 return false; 62 } 63 64 int main() 65 { 66 while(~scanf("%d %d", &n, &m)) 67 { 68 Init(n); 69 for(int i = 1; i <= n; ++i) scanf("%d", p + i); 70 for(int i = 1, u, v; i < n; ++i) 71 { 72 scanf("%d %d", &u, &v); 73 addedge(u, v); 74 } 75 int l = 0, r = n; 76 int res = 0; 77 while(r - l >= 0) 78 { 79 int mid = (l + r) >> 1; 80 if(check(mid)) 81 { 82 r = mid - 1; 83 res = mid; 84 } 85 else l = mid + 1; 86 } 87 printf("%d\n", res); 88 } 89 return 0; 90 }
D. Space Station
Unsolved.
E. Fishermen
Solved.
题意:
在一个二维平面,有有一些鱼,也有一些渔民,每个渔民有一个钓竿
渔民都在$x轴上,渔民可以钓到那条鱼的条件是它和鱼的曼哈顿距离小于等于钓竿长度$
思路:
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 2e5 + 10; 6 7 struct node{ 8 int l, r; 9 node(){} 10 node(int l,int r): l(l), r(r){} 11 bool operator < (const node &b) const 12 { 13 if(l == b.l) return r < b.r; 14 else return l < b.l; 15 } 16 }arr[maxn]; 17 18 struct qnode{ 19 int pos, idx; 20 qnode(){} 21 qnode(int pos, int idx): pos(pos), idx(idx){} 22 bool operator < (const qnode &b) const 23 { 24 return pos < b.pos; 25 } 26 }brr[maxn]; 27 28 int n, m, l; 29 int ans[maxn]; 30 31 int main() 32 { 33 while(~scanf("%d %d %d", &n, &m, &l)) 34 { 35 int pos = 0; 36 for(int i = 1; i <= n; ++i) 37 { 38 int x, y; 39 scanf("%d %d", &x ,&y); 40 if(y > l) continue; 41 int tmp = l - y; 42 arr[++pos] = node(x - tmp, x + tmp); 43 } 44 sort(arr + 1, arr + 1 + pos); 45 for(int i = 1; i <= m; ++i) 46 { 47 scanf("%d", &brr[i].pos); 48 brr[i].idx = i; 49 } 50 sort(brr + 1, brr + 1 + m); 51 priority_queue<int, vector<int>, greater<int> >q; 52 int cnt = 1; 53 for(int i = 1; i <= m; ++i) 54 { 55 while(cnt <= pos && brr[i].pos >= arr[cnt].l) 56 { 57 q.push(arr[cnt++].r); 58 } 59 while(!q.empty() && q.top() < brr[i].pos) 60 { 61 q.pop(); 62 } 63 ans[brr[i].idx] = q.size(); 64 } 65 for(int i = 1; i <= m; ++i) printf("%d\n", ans[i]); 66 } 67 return 0; 68 }
F. Min Max Convert
Unsolved.
题意:
每一次可以将一段区间的所有值变成它原先的最大或最小值
求有没有一种操作方案使得序列A 变成 序列B 如果有输出操作方案
否则输出-1
G. Matrix Queries
Unsolved.
题意:
在一个$2^n \cdot 2^n 的矩形里面,刚开始都是白色,每一次可以把一行或者一列的颜色翻转$
求每次操作后矩阵的值
这样定义矩阵的值:
如果当前矩阵的所有颜色都相同,那么该矩阵的值为1
否则将当前矩阵等分为四个,当前矩阵的值就是四个小矩阵的值+1
H. Modern Djinn
Unsolved.
I. Inversion
Solved.
题意:
在一张图中,求有多少个点集,使得这个点集里面的任意两点没有边
不在点集里面的点至少有一条边连向点集中一点
思路:
我们考虑一条边 $(i, j) 那么定义在一个序列中(i, j) 为一个逆序对$
那么就是找上升子序列的个数
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 const int maxn = 1e2 + 10; 8 9 ll dp[maxn]; 10 int G[maxn][maxn]; 11 int n, m; 12 13 int main() 14 { 15 while(~scanf("%d %d", &n, &m)) 16 { 17 memset(dp, 0, sizeof dp); 18 memset(G, 0, sizeof G); 19 for(int i = 1, u, v; i <= m; ++i) 20 { 21 scanf("%d %d", &u, &v); 22 G[u][v]++; 23 G[v][u]++; 24 } 25 dp[0] = 1 ; 26 for(int i = 1; i <= n + 1; ++i) 27 { 28 for(int j = 0; j < i; ++j) 29 { 30 if(G[i][j]) continue; 31 int flag = 1; 32 for(int k = j + 1; k < i; ++k) 33 { 34 if(G[i][k] || G[j][k]) continue; 35 else 36 { 37 flag = 0; 38 break; 39 } 40 } 41 dp[i] += flag * dp[j]; 42 } 43 } 44 printf("%lld\n", dp[n + 1]); 45 } 46 return 0; 47 }
J. Rabbit vs Turtle
Unsolved.
K. Points and Rectangles
Solved.
题意:
两种操作
一种是往一个二维平面加入一个点
还有一种是加入一个矩阵
询问每次操作后有多少个$pair(x, R)$
$pair(x, R) 表示 点x 在 矩形R 内$
思路:
考虑CDQ分治
对于每个矩阵,可以拆成四个点分治
对于每个点,我们可以把矩形的四个角赋上权值
左上角 1
左下角 -1
右上角-1
右下角1
然后把矩阵往左和网上拓宽一个单位
那么对于每个点来说就是查询右下角的值
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 100010 6 struct qnode 7 { 8 int tp, x, y, id; bool isleft; 9 qnode () {} 10 qnode (int tp, int x, int y, int id) : tp(tp), x(x), y(y), id(id) {} 11 bool operator < (const qnode &other) const { return x < other.x || x == other.x && id < other.id; } 12 }que[N << 2], tque[N << 2]; 13 int n, m, q, brr[N << 2]; 14 ll ans[N]; 15 16 void Hash() 17 { 18 sort(brr + 1, brr + 1 + m); 19 m = unique(brr + 1, brr + 1 + m) - brr - 1; 20 for (int i = 1; i <= n; ++i) que[i].y = lower_bound(brr + 1, brr + 1 + m, que[i].y) - brr; 21 } 22 23 namespace BIT 24 { 25 int a[N << 2]; 26 void init() { memset(a, 0, sizeof a); } 27 void update(int x, int val) 28 { 29 for (; x <= m; x += x & -x) 30 { 31 if (val == 0) a[x] = 0; 32 else a[x] += val; 33 } 34 } 35 ll query(int x) 36 { 37 ll res = 0; 38 for (; x; x -= x & -x) 39 res += a[x]; 40 return res; 41 } 42 } 43 44 void CDQ1(int l, int r) 45 { 46 if (l == r) return; 47 int mid = (l + r) >> 1; 48 for (int i = l; i <= r; ++i) 49 { 50 tque[i] = que[i]; 51 if (i <= mid) tque[i].isleft = true; 52 else tque[i].isleft = false; 53 } 54 sort(tque + l, tque + 1 + r); 55 for (int i = l; i <= r; ++i) 56 { 57 if (tque[i].tp == 0 && tque[i].isleft == true) BIT::update(tque[i].y, 1); 58 else if (tque[i].tp && tque[i].isleft == false)ans[tque[i].id] += BIT::query(tque[i].y) * tque[i].tp; 59 } 60 for (int i = l; i <= r; ++i) if (tque[i].tp == 0 && tque[i].isleft == true) BIT::update(tque[i].y, 0); 61 CDQ1(l, mid), CDQ1(mid + 1, r); 62 } 63 64 void CDQ2(int l, int r) 65 { 66 if (l == r) return; 67 int mid = (l + r) >> 1; 68 for (int i = l; i <= r; ++i) 69 { 70 tque[i] = que[i]; 71 if (i <= mid) tque[i].isleft = true; 72 else tque[i].isleft = false; 73 } 74 sort(tque + l, tque + 1 + r, [](qnode a, qnode b) { return a.x > b.x || a.x == b.x && a.id < b.id; }); 75 for (int i = l; i <= r; ++i) 76 { 77 if (tque[i].tp != 0 && tque[i].isleft == true) BIT::update(tque[i].y, tque[i].tp); 78 else if (tque[i].tp == 0 && tque[i].isleft == false) ans[tque[i].id] += BIT::query(m) - BIT::query(tque[i].y - 1); 79 } 80 for (int i = l; i <= r; ++i) if (tque[i].tp && tque[i].isleft == true) BIT::update(tque[i].y, 0); 81 CDQ2(l, mid); CDQ2(mid + 1, r); 82 } 83 84 int main() 85 { 86 while (scanf("%d", &q) != EOF) 87 { 88 n = 0; ans[0] = 0; m = 0; 89 memset(ans, 0, sizeof ans); 90 for (int i = 1, op, x[2], y[2]; i <= q; ++i) 91 { 92 scanf("%d%d%d", &op, x, y); 93 brr[++m] = y[0]; brr[++m] = y[0] - 1; 94 if (op == 1) que[++n] = qnode(0, x[0], y[0], i); 95 else 96 { 97 scanf("%d%d", x + 1, y + 1); 98 brr[++m] = y[1]; brr[++m] = y[1] - 1; 99 que[++n] = qnode(1, x[0] - 1, y[0] - 1, i); 100 que[++n] = qnode(1, x[1], y[1], i); 101 que[++n] = qnode(-1, x[0] - 1, y[1], i); 102 que[++n] = qnode(-1, x[1], y[0] - 1, i); 103 } 104 } 105 Hash(); BIT::init(); 106 CDQ1(1, n); CDQ2(1, n); 107 for (int i = 1; i <= q; ++i) printf("%lld\n", ans[i] += ans[i - 1]); 108 } 109 return 0; 110 }