ZOJ Monthly, January 2018 Solution

Posted dup4

tags:

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

A - Candy Game

水。

技术分享图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 1010
 5 int t, n;
 6 int a[N], b[N];
 7 
 8 int main()
 9 {
10     scanf("%d", &t);
11     while (t--)
12     {
13         scanf("%d", &n);
14         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
15         for (int i = 1; i <= n; ++i) scanf("%d", b + i);
16         puts(accumulate(a + 1, a + n + 1, 0) > accumulate(b + 1, b + 1 + n, 0) ? "BaoBao" : "DreamGrid");
17     }
18     return 0;
19 }
View Code

 

B - PreSuffix

留坑。

 

C - An Unsure Catch

留坑。

 

D - Seat Assignment

题意:给出10个数,分别表示有几个人愿意坐在编号为$i$的倍数的位置上,有m个位置,编号为1-m, 求最多坐下多少人

思路:

技术分享图片
  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 const int maxn = 1e4 + 10;
  6 const int INF = 0x3f3f3f3f;
  7 
  8 
  9 struct Edge{
 10     int from;
 11     int to;
 12     int cap;
 13     int flow;
 14     Edge(){}
 15     Edge(int from, int to, int cap, int flow) :from(from), to(to), cap(cap), flow(flow){}
 16 };
 17 
 18 int S, T;
 19 vector<Edge>edge;
 20 vector<int>G[maxn];
 21 int arr[maxn];
 22 int vis[maxn];
 23 int d[maxn];
 24 int cur[maxn];
 25 int cnt;
 26 int mark[maxn];
 27 int limit[maxn];
 28 int number[maxn];
 29 
 30 void Init()
 31 {
 32     edge.clear();
 33     for(int i = 0; i < 100; ++i) G[i].clear();
 34 }
 35 
 36 void addedge(int from, int to, int cap)
 37 {
 38     edge.push_back(Edge(from, to, cap, 0));
 39     edge.push_back(Edge(to, from, 0, 0));
 40     int len = edge.size();
 41     G[from].push_back(len - 2);
 42     G[to].push_back(len - 1);
 43 }
 44 
 45 bool BFS()
 46 {
 47     memset(d, 0, sizeof d);
 48     memset(vis, 0, sizeof vis);
 49     queue<int>q;
 50     q.push(S);
 51     d[S] = 1;
 52     vis[S] = 1;
 53     while(!q.empty())
 54     {
 55         int x = q.front();
 56         q.pop();
 57         for(int i = 0, len = G[x].size(); i < len; ++i)
 58         {
 59             Edge &e = edge[G[x][i]];
 60             if(!vis[e.to] && e.cap > e.flow)
 61             {
 62                 vis[e.to] = 1;
 63                 d[e.to] = d[x] + 1;
 64                 q.push(e.to);
 65             }
 66         }
 67     }
 68     return vis[T];
 69 }
 70 
 71 int DFS(int x, int a)
 72 {
 73     if(x == T || a == 0) return a;
 74     int flow = 0;
 75     int f;
 76     for(int &i = cur[x]; i < G[x].size(); ++i)
 77     {
 78         Edge &e = edge[G[x][i]];
 79         if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0)
 80         {
 81             e.flow += f;
 82             edge[G[x][i] ^ 1].flow -= f;
 83             flow += f;
 84             a -= f;
 85             if(a == 0) break;
 86         }
 87     }
 88     return flow;
 89 }
 90 
 91 int dicnic()
 92 {
 93     int ans = 0;
 94     while(BFS())
 95     {
 96         memset(cur, 0, sizeof cur);
 97         ans += DFS(S, INF);
 98     }
 99     return ans;
100 }
101 
102 void init()
103 {
104     cnt = 0;
105     for(int i = 0; i < 2520; ++i)
106     {
107         int S = 0;
108         for(int j = 1; j <= 10; ++j)
109         {
110             if(i % j == 0) S |= (1 << j);
111         }
112         if(!vis[S])
113         {
114             cnt++;
115             vis[S] = cnt;
116             number[cnt] = S;
117         }
118         mark[i] = vis[S];
119     }
120 }
121 
122 
123 int main()
124 {
125     init();
126     int t;
127     scanf("%d", &t);
128     while(t--)
129     {
130         int n;
131         scanf("%d", &n);
132         Init();
133         memset(limit, 0, sizeof limit);
134         S = 0, T = 59;
135         for(int i = 0; i < 2520; ++i)
136         {
137             int num = n / 2520;
138             if(i >= 1 && n % 2520 >= i) num++;
139             limit[mark[i]] += num;
140         }
141         for(int i = 1; i <= 48; ++i)
142         {
143             addedge(i + 10, T, limit[i]);
144         }
145         for(int i = 1; i <= 10; ++i)
146         {
147             scanf("%d", arr + i);
148             if(arr[i])
149             {
150                 addedge(S, i, arr[i]);
151                 for(int j = 1; j <= 48; ++j)
152                 {
153                     if(number[j] & (1 << i))
154                     {
155                         addedge(i, j + 10, arr[i]);
156                     }
157                 }
158             }
159         }
160         int ans = dicnic();
161         printf("%d
", ans);
162     }
163 }
View Code

 

 

E - Yet Another Data Structure Problem

题意:三种操作,一种是区间乘一个数v,一种是把区间内每个数都变成其k次方,还有一种是求区间乘积
思路:增加两个lazy操作,一种是幂次,一种是乘数

更新幂次的时候顺带把乘积更新一下

再考虑费马小定理 把幂次$模(MOD - 1)$

技术分享图片
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define N 100010
  5 #define ll long long
  6 const ll MOD = (ll)1e9 + 7;
  7 int t, n, q;
  8 ll arr[N];
  9 
 10 ll qmod(ll base, ll n)
 11 {
 12     ll res = 1;
 13     while (n)
 14     {
 15         if (n & 1) res = res * base % MOD;
 16         base = base * base % MOD;
 17         n >>= 1;
 18     }
 19     return res;
 20 }
 21 
 22 struct SEG
 23 {
 24     ll lazy[N << 2][2], mul[N << 2];
 25     void pushup(int id) { mul[id] = (mul[id << 1] * mul[id << 1 | 1]) % MOD; }
 26        void build(int id, int l, int r)  
 27     {
 28         lazy[id][0] = 1; lazy[id][1] = 1; 
 29         if (l == r)
 30         {
 31             mul[id] = arr[l];
 32             return;
 33         }
 34         int mid = (l + r) >> 1;
 35         build(id << 1, l, mid);
 36         build(id << 1 | 1, mid + 1, r);
 37         pushup(id);
 38     }    
 39     void pushdown(int id, int l, int r)
 40     {
 41         if (lazy[id][1] != 1) 
 42         {
 43             lazy[id << 1][1] = (lazy[id << 1][1] * lazy[id][1]) % (MOD - 1);
 44             lazy[id << 1][0] = qmod(lazy[id << 1][0], lazy[id][1]);
 45             mul[id << 1] = qmod(mul[id << 1], lazy[id][1]); 
 46             lazy[id << 1 | 1][1] = (lazy[id << 1 | 1][1] * lazy[id][1]) % (MOD - 1);
 47             lazy[id << 1 | 1][0] = qmod(lazy[id << 1 | 1][0], lazy[id][1]);
 48             mul[id << 1 | 1] = qmod(mul[id << 1 | 1], lazy[id][1]);
 49             lazy[id][1] = 1; 
 50         }
 51         if (lazy[id][0] != 1)
 52         {
 53             int mid = (l + r) >> 1;
 54             lazy[id << 1][0] = (lazy[id << 1][0] * lazy[id][0]) % MOD;
 55             mul[id << 1] = (mul[id << 1] * qmod(lazy[id][0], (mid - l + 1))) % MOD;
 56             lazy[id << 1 | 1][0] = (lazy[id << 1 | 1][0] * lazy[id][0]) % MOD;
 57             mul[id << 1 | 1] = (mul[id << 1 | 1] * qmod(lazy[id][0], (r - mid))) % MOD;
 58             lazy[id][0] = 1;
 59         }
 60     }
 61     void update0(int id, int l, int r, int ql, int qr, ll v)
 62     {
 63         if (l >= ql && r <= qr)
 64         {
 65             lazy[id][0]    = (lazy[id][0] * v) % MOD;
 66             mul[id] = (mul[id] * qmod(v, (r - l + 1))) % MOD;
 67             return;
 68         }
 69         pushdown(id, l, r);
 70         int mid = (l + r) >> 1;
 71         if (ql <= mid) update0(id << 1, l, mid, ql, qr, v);
 72         if (qr > mid) update0(id << 1 | 1, mid + 1, r, ql, qr, v);
 73         pushup(id);
 74     }
 75     void update1(int id, int l, int r, int ql, int qr, ll v)
 76     {
 77         if (l >= ql && r <= qr)
 78         {
 79             lazy[id][0] = qmod(lazy[id][0], v);
 80             mul[id] = qmod(mul[id], v);
 81             lazy[id][1] = (lazy[id][1] * v) % (MOD - 1);
 82             return;
 83         }
 84         pushdown(id, l, r);
 85         int mid = (l + r) >> 1;
 86         if (ql <= mid) update1(id << 1, l, mid, ql, qr, v);
 87         if (qr > mid) update1(id << 1 | 1, mid + 1, r, ql, qr, v);
 88         pushup(id);
 89     }
 90     ll query(int id, int l, int r, int ql, int qr)
 91     {
 92         if (l >= ql && r <= qr) return mul[id];
 93         pushdown(id, l, r);
 94         int mid = (l + r) >> 1;
 95         ll res = 1;
 96         if (ql <= mid) res = (res * query(id << 1, l, mid, ql, qr)) % MOD;
 97         if (qr > mid) res = (res * query(id << 1 | 1, mid + 1, r, ql, qr)) % MOD;
 98         pushup(id);
 99         return res;
100     }
101 }seg;
102 
103 int main()
104 {
105     scanf("%d", &t);
106     while (t--)
107     {
108         scanf("%d%d", &n, &q);
109         for (int i = 1; i <= n; ++i) scanf("%lld", arr + i);
110         seg.build(1, 1, n);
111         for (int i = 1, op, l, r, v; i <= q; ++i)
112         {
113             scanf("%d%d%d", &op, &l, &r);
114             if (op == 3) printf("%lld
", seg.query(1, 1, n, l, r));
115             else
116             {
117                 scanf("%d", &v);
118                 if (op == 1) seg.update0(1, 1, n, l, r, v);
119                 else seg.update1(1, 1, n, l, r, v);
120             }    
121         }
122     }
123     return 0;
124 }
View Code

 

F - The Limit

题意:给出两个多项式,求极限

思路:四种情况,分别讨论即可。注意字符串的处理,以及最后负号的判断

技术分享图片
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define ll long long
  5 int t; ll x;
  6 struct node
  7 {
  8     ll a[20];
  9     void scan()
 10     {
 11         memset(a, 0, sizeof a);
 12         string s; cin >> s;  
 13         if (s[0] != -) s.insert(0, "+"); 
 14         while (1)
 15         {
 16             bool flag = 0;
 17             for (int i = 0, len = s.size(); i < len; ++i)
 18             {
 19                 if (s[i] == x && (i == len - 1 || s[i + 1] != ^))
 20                 {
 21                     s.insert(i + 1, "^1");
 22                     flag = 1;
 23                     break;
 24                 }
 25             }
 26             if (!flag) break;
 27         }
 28         while (1)
 29         {
 30             bool flag = 0;
 31             for (int i = 0, len = s.size(); i < len; ++i)
 32             {
 33                 if (isdigit(s[i]) && (s[i - 1] == + || s[i - 1] == -) && (i == len - 1 || s[i + 1] == + || s[i + 1] == -))
 34                 {
 35                     s.insert(i + 1, "x^0"); 
 36                     flag = 1;
 37                     break;
 38                 }
 39             }
 40             if (!flag) break;
 41         }
 42         while (1)
 43         {
 44             bool flag = 0;
 45             for (int i = 0, len = s.size(); i < len; ++i) 
 46             {
 47                 if (s[i] == x && !isdigit(s[i - 1]))
 48                 {
 49                     s.insert(i, "1");  
 50                     flag = 1;
 51                     break;
 52                 }
 53             }
 54             if (!flag) break;
 55         }
 56         for (int i = 0, len = s.size(); i < len; ++i)
 57         {
 58             if (s[i] == ^)
 59             {
 60                 int pos = s[i + 1] - 0;
 61                 int base = (s[i - 2] - 0) * (s[i - 3] == + ? 1 : -1);
 62                 a[pos] += base;
 63             }
 64         }
 65     }
 66     ll calc()
 67     {
 68         ll res = 0;
 69         ll base = 1;
 70         for (int i = 0; i <= 9; ++i, base *= x)
 71             res += base * a[i]; 
 72         return res;
 73     }
 74     void luo()
 75     {
 76         for (int i = 0; i < 9; ++i)
 77             a[i] = a[i + 1] * (ll)(i + 1);
 78     }
 79     
 80 }fenzi, fenmu;
 81 
 82 ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
 83 
 84 void solve()
 85 {
 86     while (1)
 87     {
 88         ll a = fenzi.calc(), b = fenmu.calc();
 89         if (a == 0 && b == 0)
 90         {
 91             fenzi.luo();
 92             fenmu.luo();
 93         }
 94         else if (a == 0)
 95         {
 96             cout << "0
"; 
 97             return;
 98         }
 99         else if (b == 0)
100         {
101             cout << "INF
";
102             return;
103         }
104         else if (a && b)
105         {
106             int vis = (a < 0 || b < 0) && !(a < 0 && b < 0);
107             a = abs(a), b = abs(b);
108             ll GCD = gcd(a, b);
109             a /= GCD, b /= GCD;
110             if (vis) cout << "-"; 
111             if (b == 1)
112                     cout << a << "
";
113             else
114                 cout << a << "/" << b << "
";
115             return;
116         }
117     }    
118 }
119 
120 int main()
121 {
122     ios::sync_with_stdio(false);
123     cin.tie(0);
124     cout.tie(0);
125     cin >> t;
126     while (t--)
127     {
128         fenzi.scan();
129         fenmu.scan();
130         cin >> x;
131         solve();
132     }
133     return 0;
134 }
View Code

 

G - It‘s High Noon

留坑。

 

H - Traveling Plan

题意:有些城市有补给,有些没有,经过一条路要消耗这条路的边权的补给,每次询问两个补给点,需要多大容量的背包

思路:先将所有补给点作源点跑最短路,然后更新每条边权为这条边本身的边权加两个端点到最近的补给点的距离,然后求最小生成树

倍增维护最大

技术分享图片
  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 typedef long long ll;
  6 const ll INFLL = 0x3f3f3f3f3f3f3f3f;
  7 const int maxn = 2e5 + 10;
  8 const int DEG = 20;
  9 
 10 struct qnode{
 11     int to;
 12     ll val;
 13     qnode(){}
 14     qnode(int to, ll val) :to(to), val(val){}
 15     bool operator < (const qnode &b) const
 16     {
 17         return val > b.val;
 18     }    
 19 };
 20 
 21 struct node{
 22     int u, v;
 23     ll w;
 24     bool operator < (const node &b) const
 25     {
 26         return w < b.w;
 27     }
 28 }tmp[maxn << 1];
 29 
 30 struct Edge{
 31     int to, nxt;
 32     ll w;
 33     Edge(){}
 34     Edge(int to, int nxt, ll w) : to(to), nxt(nxt), w(w){}
 35 }edge[maxn << 1];
 36 
 37 int n, m;
 38 int fa[maxn][DEG];
 39 int deg[maxn];
 40 ll dist[maxn][DEG];
 41 vector<qnode>G[maxn];
 42 int vis[maxn];
 43 int head[maxn];
 44 ll dis[maxn];
 45 int tot;
 46 priority_queue<qnode>q;
 47 int father[maxn];
 48 
 49 void Init(int N)
 50 {
 51     for(int i = 1; i <= N; ++i) 
 52     {
 53         dis[i] = INFLL;
 54         father[i] = i;
 55         head[i] = -1;
 56         G[i].clear();
 57     }
 58     tot = 0;
 59 }
 60 int find(int x)
 61 {
 62     return x == father[x] ? father[x] : father[x] = find(father[x]);
 63 }
 64 
 65 bool same(int x,int y)
 66 {
 67     return find(x) == find(y);
 68 }
 69 
 70 void mix(int x, int y)
 71 {
 72     x = find(x);
 73     y = find(y);
 74     if(x != y)
 75     {
 76         father[x] = y;
 77     }
 78 }
 79 
 80 void addedge(int u, int v, ll w)
 81 {
 82     edge[tot] = Edge(v, head[u], w); head[u] = tot++;
 83     edge[tot] = Edge(u, head[v], w); head[v] = tot++;
 84 }
 85 
 86 void Dijkstra()
 87 {
 88     while(!q.empty())
 89     {
 90         qnode tmp = q.top();
 91         q.pop();
 92         int u = tmp.to;
 93         if(tmp.val > dis[u]) continue;
 94         for(int i = 0, len = G[u].size(); i < len; ++i)
 95         {
 96             int v = G[u][i].to;
 97             ll cost = G[u][i].val;
 98             if(dis[v] > dis[u] + cost)
 99             {
100                 dis[v] = dis[u] + cost;
101                 q.push(qnode(v, dis[v]));
102             }
103         }
104     }
105 }
106 
107 void BFS(int root)
108 {
109     queue<int>que;
110     deg[root] = 0;
111     fa[root][0] = root;
112     dist[root][0] = 0;
113     que.push(root);
114     while(!que.empty())
115     {
116         int tmp = que.front();
117         que.pop();
118         for(int i = 1; i < DEG; ++i)
119         {
120             fa[tmp][i] = fa[fa[tmp][i - 1]][i - 1];
121             dist[tmp][i] = max(dist[tmp][i - 1], dist[fa[tmp][i - 1]][i - 1]);
122         }
123         for(int i = head[tmp]; ~i; i = edge[i].nxt)
124         {
125             int v = edge[i].to;
126             if(v == fa[tmp][0]) continue;
127             deg[v] = deg[tmp] + 1;
128             dist[v][0] = edge[i].w;
129             fa[v][0] = tmp;
130             que.push(v);
131         }
132     }
133 }
134 
135 ll LCA(int u, int v)
136 {
137     ll res = 0;
138     if(deg[u] > deg[v]) swap(u, v);
139     int hu = deg[u], hv = deg[v];
140     int tu = u, tv = v;
141     for(int det = hv - hu, i = 0; det; det >>= 1, ++i)
142     {
143         if(det & 1)
144         {
145             res = max(res, dist[tv][i]);
146             tv = fa[tv][i];
147         }
148     }
149     if(tu == tv) return res;
150     for(int i = DEG - 1; i >= 0; --i)
151     {
152         if(fa[tu][i] == fa[tv][i]) continue;
153         res = max(res, dist[tu][i]);
154         res = max(res, dist[tv][i]);
155         tu = fa[tu][i];
156         tv = fa[tv][i];
157     }
158     return max(res, max(dist[tu][0], dist[tv][0]));
159 }
160 
161 int main()
162 {
163     while(~scanf("%d %d", &n, &m))
164     {
165         Init(n);
166         int root;
167         for(int i = 1; i <= n; ++i)
168         {
169             scanf("%d", vis + i);
170             if(vis[i] == 1)
171             {
172                 dis[i] = 0;
173                 q.push(qnode(i, 0));
174             }
175             else root = i;
176         }
177         for(int i = 1; i <= m; ++i)
178         {
179             scanf("%d %d %lld", &tmp[i].u, &tmp[i].v, &tmp[i].w);
180             G[tmp[i].u].push_back(qnode(tmp[i].v, tmp[i].w));
181             G[tmp[i].v].push_back(qnode(tmp[i].u, tmp[i].w));
182         }
183         Dijkstra();    
184     //    for(int i = 1; i <= n; ++i) cout << i << " " << dis[i] << endl;
185         for(int i = 1; i <= m; ++i) tmp[i].w += dis[tmp[i].u] + dis[tmp[i].v];
186         sort(tmp + 1, tmp + 1 + m);
187         for(int i = 1; i <= m; ++i)
188         {
189             if(same(tmp[i].u, tmp[i].v)) continue;
190             mix(tmp[i].u, tmp[i].v);
191             addedge(tmp[i].u, tmp[i].v, tmp[i].w);
192         }
193         BFS(root);
194         int q;
195         scanf("%d", &q);
196         while(q--)
197         {
198             int u, v;
199             scanf("%d %d", &u, &v);
200             ll ans = LCA(u, v);
201             printf("%lld
", ans);
202         }
203     }
204     return 0;
205 }
View Code

 

I - Wooden Bridge
留坑。

 

J - Distance

题意:定义多维空间的距离为$sum |a_i - b_i|^p$ 求有多少x的子串和y的子串形成的坐标的距离小于v 子串长度要相同
思路:固定x起点,双指针找y的两个端点

技术分享图片
 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const int maxn = 1e3 + 10;
 7 
 8 int n, p;
 9 ll V;
10 ll arr[maxn], brr[maxn];
11 ll cnt[maxn << 1], val[maxn << 1];
12 
13 ll calc(int i, int j)
14 {
15     ll tmp = abs(arr[i] - brr[j]);
16     ll res = 1;
17     for(int i = 1; i <= p; ++i) res = res * tmp;
18     return res;
19 }
20 
21 int main()
22 {
23     int t;
24     scanf("%d", &t);
25     while(t--)
26     {
27         scanf("%d %lld %d", &n ,&V ,&p);
28         memset(cnt, 0, sizeof cnt);
29         memset(val, 0, sizeof val);
30         for(int i = 1; i <= n; ++i) scanf("%lld", arr + i);
31         for(int i = 1; i <= n; ++i) scanf("%lld", brr + i);
32         ll ans = 0;
33         for(int i = 1; i <= n; ++i)
34         {
35             for(int j = 1; j <= n; ++j)
36             {
37                 int tmp = i - j + n;
38                 cnt[tmp]++;
39                 val[tmp] += calc(i, j);
40                 while(cnt[tmp] > 0 && val[tmp] > V)
41                 {
42                     cnt[tmp]--;
43                     val[tmp] -= calc(i - cnt[tmp], j - cnt[tmp]);
44                 }
45                 ans += cnt[tmp];
46             }
47         }
48         printf("%lld
", ans);
49     }
50     return 0;
51 }
View Code

 




以上是关于ZOJ Monthly, January 2018 Solution的主要内容,如果未能解决你的问题,请参考以下文章

ZOJ Monthly, January 2019

ZOJ Monthly, January 2019 I Little Sub and Isomorphism Sequences(set 妙用) ZOJ4089

ZOJ Monthly, January 2019 Little Sub and Isomorphism Sequences 离线离散化 + set + multiset

ZOJ Monthly, March 2018

ZOJ Monthly, June 2018 - I District Division

ZOJ Monthly, March 2018 Solution