2019 ICPC Nanjing Regional Online Contest

Posted jhseng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019 ICPC Nanjing Regional Online Contest相关的知识,希望对你有一定的参考价值。

比较自闭的一场网络赛,题目质量不错。

题目链接:https://www.jisuanke.com/contest/3004


A:

upsolver: czq

经典的二维偏序问题,求(x,y)左下角点的个数。对x和y升序排序,用树状数组维护每个纵坐标y已经出现的次数,这样就可以动态把点的纵坐标加入树状数组,然后求出比y小的有多少个(树状数组求和)就可以知道当前点的二维偏序值。这道题并不需要离散化,直接开1e6的树状数组即可。

技术图片
 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define dou double
 6 #define pb emplace_back
 7 #define mp make_pair
 8 #define sot(a,b) sort(a+1,a+1+b)
 9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
10 #define rep0(i,a,b) for(int i=a;i<b;++i)
11 #define eps 1e-8
12 #define int_inf 0x3f3f3f3f
13 #define ll_inf 0x7f7f7f7f7f7f7f7f
14 #define lson (curpos<<1)
15 #define rson (curpos<<1|1)
16 /* namespace */
17 using namespace std;
18 /* header end */
19 
20 const int maxn = 1e6 + 10;
21 struct Point 
22     int x, y, val, id;
23     Point() 
24     Point(int a, int b, int c, int d): x(a), y(b), val(c), id(d) 
25     bool operator<(const Point &rhs)const 
26         return x != rhs.x ? x < rhs.x : y != rhs.y ? y < rhs.y : id < rhs.id;
27     
28  p[maxn];
29 
30 int n, m, q, len;
31 ll ans[maxn];
32 
33 struct BIT 
34     int bit[maxn];
35 
36     void init(int n) 
37         rep0(i, 0, n) bit[i] = 0;
38     
39 
40     int lowbit(int x) 
41         return x & -x;
42     
43 
44     void add(int pos, int val) 
45         while (pos <= n) 
46             bit[pos] += val;
47             pos += lowbit(pos);
48         
49     
50 
51     ll query(int pos) 
52         ll res = 0;
53         while (pos) 
54             res += bit[pos];
55             pos -= lowbit(pos);
56         
57         return res;
58     
59  bit;
60 
61 int getval(int x, int y) 
62     x = n + 1 - x, y = n + 1 - y;
63     ll ans = 0, minn = min(x, min(y, min(n - x + 1, n - y + 1))), ret = 0;
64     ans = x <= y ? minn * (4 * (n - 1) - 4 * minn) + 10 * minn - 4 * n - 3 + x + y : minn * (4 * n - 4 * minn) + 2 * minn + 1 - x - y;
65     while (ans) 
66         ret += ans % 10;
67         ans /= 10;
68     
69     return ret;
70 
71 
72 int main() 
73     int t; scanf("%d", &t);
74     while (t--) 
75         scanf("%d%d%d", &n, &m, &q); len = m;
76         bit.init(n);
77         rep1(i, 1, m) 
78             int x, y; scanf("%d%d", &x, &y);
79             p[i] = Point(x, y, getval(x, y), 0);
80         
81         rep1(i, 1, q) 
82             ans[i] = 0;
83             int x1, x2, y1, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
84             p[++len] = Point(x1 - 1, y1 - 1, 1, i); // when id != 0, means reaching a boarder of rectangle
85             p[++len] = Point(x2, y2, 1, i);
86             p[++len] = Point(x1 - 1, y2, -1, i);
87             p[++len] = Point(x2, y1 - 1, -1, i);
88         
89         sort(p + 1, p + 1 + len);
90         for (int i = 1; i <= len; i++) //enum each point
91             if (p[i].id) ans[p[i].id] += bit.query(p[i].y) * p[i].val; // if it‘s a boarder
92             else bit.add(p[i].y, p[i].val); // else add contribution to ans
93         rep1(i, 1, q) printf("%lld\n", ans[i]);
94     
95     return 0;
96 
View Code

B:

upsolver: rsq

容易猜到答案是a^a^a%mod,因为幂次很高所以要欧拉降幂。队友不知道什么地方写挂了。

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1111111;
 4 typedef long long ll;
 5 bool check[maxn];
 6 ll phi[maxn];
 7 ll prime[maxn];
 8 ll cnt;
 9 
10 void getphi(ll lim)
11 
12     phi[1] = 1ll;
13     cnt = 0;
14     check[1] = true;
15     for(ll i = 2;i <= lim;i++)
16         if(!check[i])
17             prime[++cnt] = i;
18             phi[i] = i-1;
19         
20         for(ll j = 1ll;j <= cnt;j++)
21             if(i * prime[j] >= lim) break;
22             check[i * prime[j]] = true;
23             if((i % prime[j]) == 0ll)
24                 phi[i * prime[j]] = phi[i] * prime[j];
25                 break;
26             else 
27                 phi[i * prime[j]] = phi[i] * (prime[j] - 1);
28             
29         
30     
31 
32 
33 ll getpow(ll a,ll b,ll m)
34 
35     ll ret = 1ll;
36     ll tmp = a;
37     while(b)
38         if(b&1)
39             ret = ret * tmp;
40             if(ret >= m)
41                 ret = ret % m + m;
42             
43         
44         tmp = tmp * tmp;
45         if(tmp >= m)
46             tmp = tmp % m + m;
47         
48         b >>= 1;
49     
50     return ret;
51 
52 
53 ll solve(ll a,ll b,ll m)
54 
55     if(b == 0ll) return 1ll;
56     if(m == 1) return 1ll;
57     ll pos = solve(a,b-1,phi[m]);
58     return getpow(a,pos,m);
59     
60 
61 int main()
62     getphi(1000000);
63     ll T;
64     cin >> T;
65     while(T--)
66         ll a,b,m;
67         cin >> a >> b >> m;
68         cout << solve(a,b,m) % m << endl;            
69     
70     return 0;
71 
View Code

F:

solver: zyh, czq

题意很鬼的一题。给定一个全排列,要求构造若干个数列。第i个数列的首个元素必须为i,该序列不上升,该序列中正整数元素在全排列中只能出现一次;对于序列中相邻的元素,若均为正整数,则它们在给定的全排列中的下标只差不能超过给定的正整数k。规定比1小的数只有0。

其实做法还算简单。就是扫一遍全排列,对于每个元素,找区间[i-k,i+k]内的最优解,并看作从i到解连一条有向边;这样,对于出度为0的点,给他们分配一个根节点,就可以弄成一棵树,每个节点的答案就是到根节点的距离-1。

技术图片
 1 /* Contest nanjing_2019_online
 2  * Problem F
 3  * Team: Make One For Us
 4  */
 5 #include <bits/stdc++.h>
 6 #include <bits/extc++.h>
 7 
 8 using namespace std;
 9 using namespace __gnu_pbds;
10 
11 int arr[100005], ans[100005];
12 
13 int read(void) 
14     char ch;
15     do 
16         ch = getchar();
17      while (!isdigit(ch));
18     int ret = 0;
19     while (isdigit(ch)) 
20         ret *= 10;
21         ret += ch - 0;
22         ch = getchar();
23     
24     return ret;
25 
26 
27 int main(void) 
28     int T;
29     T = read();
30     while (T--) 
31         int n, k;
32         n = read();
33         k = read();
34         for (int i = 0; i < n; i++) 
35             arr[i] = read();
36         
37         tree <int, null_type, less <int>, rb_tree_tag> ruler;
38         for (int i = 0; i < k; i++) ruler.insert(arr[i]);
39         vector <vector <int>> father(n + 1);
40         for (int i = 0; i < n; i++) 
41             if (i + k < n) ruler.insert(arr[i + k]);
42             if (i - k - 1 >= 0) ruler.erase(arr[i - k - 1]);
43             auto nxt = ruler.lower_bound(arr[i]);
44             if (nxt != ruler.begin()) 
45                 auto val = *--nxt;
46                 father[val].emplace_back(arr[i]);
47              else father[0].emplace_back(arr[i]);
48         
49         queue <pair <int, int>> q;
50         q.emplace(make_pair(0, 0));
51         while (!q.empty()) 
52             auto t = q.front();
53             q.pop();
54             ans[t.first] = t.second;
55             for (auto &e : father[t.first]) q.emplace(make_pair(e, t.second + 1));
56         
57         for (int i = 1; i <= n; i++) printf("%d%c", ans[i], i < n ?   : \n);
58     
59     return 0;
60 
View Code

H:

solver: zyh, czq

给定从s到t建边,那么就是从t到s跑6次bellman ford即可。

技术图片
 1 /* Contest nanjing_2019_online
 2  * Problem H
 3  * Team: Make One For Us
 4  */
 5 #include <bits/stdc++.h>
 6 
 7 using namespace std;
 8 
 9 int n, m;
10 const long long int INF = 1000000000000000LL;
11 
12 struct edge 
13     int u, v;
14     long long int w;
15 ;
16 
17 long long int bellman_ford(int s, int t, vector <vector <int>> &g,  vector <edge> &edges) 
18     queue <int> q;
19     vector <long long int> dis(n);
20     vector <bool> inq(n);
21     for (int i = 0; i < n; i++) 
22         dis[i] = INF;
23     
24     dis[s] = 0;
25     inq[s] = true;
26     q.push(s);
27     while (!q.empty()) 
28         int u = q.front();
29         q.pop();
30         inq[u] = false;
31         for (auto eid : g[u]) 
32             edge &e = edges[eid];
33             if (dis[e.u] < INF && dis[e.v] > dis[e.u] + e.w) 
34                 dis[e.v] = dis[e.u] + e.w;
35                 if (!inq[e.v]) 
36                     q.push(e.v);
37                     inq[e.v] = true;
38                 
39             
40         
41     
42     return dis[t];
43 
44 
45 int main(void) 
46     int T;
47     scanf("%d", &T);
48     while (T--) 
49         scanf("%d %d", &n, &m);
50         vector <vector <int>> g(n);
51         vector <edge> edges(m);
52         for (int i = 0; i < m; i++) 
53             scanf("%d %d %lld", &edges[i].u, &edges[i].v, &edges[i].w);
54             g[edges[i].u].emplace_back(i);
55         
56         for (int i = 0; i < 6; i++) 
57             int s, t;
58             scanf("%d %d", &s, &t);
59             long long int nw = -bellman_ford(t, s, g, edges);
60             printf("%lld\n", nw);
61             edges.emplace_back((edge) 
62                 s, t, nw
63             );
64             g[s].emplace_back(m + i);
65         
66     
67     return 0;
68 
View Code

 

以上是关于2019 ICPC Nanjing Regional Online Contest的主要内容,如果未能解决你的问题,请参考以下文章

2019 ICPC Nanjing Regional Online Contest

计蒜客 The Preliminary Contest for ICPC Asia Nanjing 2019

2019 ICPC Asia Nanjing Regional F. Paper Grading

The Preliminary Contest for ICPC Asia Nanjing 2019/2019南京网络赛——题解

The Preliminary Contest for ICPC Asia Nanjing 2019 D. Robots(概率dp)

2018-2019 ACM-ICPC, Asia Nanjing Regional Contest(J Prime Game)