2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2018) Solution

A. Numbers

Unsolved.

 

B. Broken Watch

Solved.

题意:

一个圆盘上,有等分的n块区域,有三根指针,当三根指针分别位于两块区域的交界处时

指针的三点相连会形成一个三角形,求有多少个三角包含三指针的起点(即交汇处)

思路:

 1 #include
 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 }
View Code

 

C. Tree

Solved.

题意:

一棵树中,有些点是黑点,有些点是白点,求恰选择m个黑点

使得黑点中任意两点的最长距离最短

思路:

 1 #include
 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 }
View Code

 

 

D. Space Station

Unsolved.

 

E. Fishermen

Solved.

题意:

在一个二维平面,有有一些鱼,也有一些渔民,每个渔民有一个钓竿

渔民都在$x轴上,渔民可以钓到那条鱼的条件是它和鱼的曼哈顿距离小于等于钓竿长度$

思路:

 1 #include
 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 }
View Code

 

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
 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 }
View Code

 

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 
  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 }
View Code

 

转载于:https://www.cnblogs.com/Dup4/p/10055176.html

你可能感兴趣的:(2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2018) Solution)