A.Alyona and copybooks

Problems: 给你一个数n和代价分别为a, b, c、数量不限的1, 2, 3,求将n凑成4的倍数的最小代价

Analysis:

  cj:取个模随便凑一凑就好

Tags: Implementation

 1 #define PRON "pa"
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 
 9 inline ll _min(ll a, ll b, ll c){
10     return min(a, min(b, c));
11 }
12 
13 int main(){
14     ll n, a, b, c;
15     cin >> n >> a >> b >> c;
16 
17     ll r = n % 4, ans = 0;
18     if (r == 1)
19         ans = _min(3 * a, a + b, c);
20     if (r == 2)
21         ans = _min(2 * a, b, c * 2);
22     if (r == 3)
23         ans = _min(a, b * 2 + c, c * 3);
24 
25     cout << ans;
26 }
code by cj

 

B.Alyona and flowers

Problems: 一个数列,每次操作选择一个区间[l, r];若a[i]被选择了b[i]次,则Alyona的幸福值增加a[i] * b[i];保留一些操作使得最后幸福值最高。

Analysis:

  cj:对于每次操作,对于幸福值的贡献是sum{a[l], a[l + 1], ... , a[r]},只要贡献是正的的操作就保留

Tags: Implementation

 1 #define PRON "pb"
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 #define inf 0x3f3f3f3f
 7 using namespace std;
 8 typedef long long ll;
 9 
10 const int maxn = 100 + 10;
11 
12 int n, m, a[maxn];
13 
14 int main(){
15 #ifndef ONLINE_JUDGE
16     freopen(PRON ".in", "r", stdin);
17 #endif
18 
19     cin >> n >> m;
20     for (int i = 1; i <= n; i ++)
21         cin >> a[i];
22 
23     int ans = 0, temp, l, r;
24     while (m --){
25         cin >> l >> r;
26 
27         temp = 0;
28         for (int i = l; i <= r; i ++)
29             temp += a[i];
30         if (temp > 0)
31             ans += temp;
32     }
33 
34     cout << ans << endl;
35 }
code by cj

 

C.Alyona and mex

Problems: 给定m个区间,构造一个长度为n的数列,使得每个区间的mex的最小值最大。

Analysis:

  cj:首先这个mex的最小值的最大值显然是min_mex = min{r[i] - l[i] + 1};最简单的构造办法就是用{1, 2, 3 ..., min_mex - 1}来填充这个数列。

Tags: Constructive Algorithms

 1 #define PRON "pc"
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 #define inf 0x3f3f3f3f
 7 using namespace std;
 8 typedef long long ll;
 9 
10 const int maxn = 2e5 + 10;
11 
12 int n, m;
13 pair<int, int> a[maxn];
14 
15 bool cmp(pair<int, int> A, pair<int, int> B){
16     return A.second - A.first < B.second - B.first;
17 }
18 
19 int main(){
20 #ifndef ONLINE_JUDGE
21     freopen(PRON ".in", "r", stdin);
22 #endif
23 
24     cin >> n >> m;
25 
26     int mex = inf;
27     for (int i = 0; i < m; i ++){
28         cin >> a[i].first >> a[i].second;
29         mex = min(mex, 1 + a[i].second - a[i].first);
30     }
31 
32     cout << mex << endl;
33 
34     for (int i = 1; i <= n; i ++)
35         cout << i % mex << " ";
36     cout << endl;
37 }
code by cj

 

D. Alyona and a tree

Problems: 一棵以1为根的树和各边的长度,给定每个点有一个值a。当dis(v, u) < a[u]并且u在v的子树中就认为u控制了v。问每个点控制了多少个点。

Analysis:

  cj:dis(v, u) < a[u]可以变成d[u] - d[v] < a[u],即:d[v] > d[u] - a[u],其中d[i]表示dis(1, i)。用vector来维护dfs序,显然d是递增的,所以每次二分查找这个v,使得v以上的所以点都不能控制u,以下的点都可以控制u。用数组c来记录答案,初值赋1,装作能被控制的样子,对于一个点x,c[x] = sum{c[i]},i是x的子树中的点。所以当查找到v之后,将这条链上v的亲爸爸的c减1,这样的话更新答案的时候就不会加上这个点及其以上的点。最后输出c[i] - 1即可。

Tags: binary search, dfs

 1 #define PRON "pd"
 2 #include <vector>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <algorithm>
 7 #define inf 0x3f3f3f3f
 8 using namespace std;
 9 typedef long long ll;
10 
11 const int maxn = 2e5 + 10;
12 
13 struct Edge {
14     int to, d;
15     Edge * next;
16 } e[maxn], * head[maxn];
17 
18 vector<int> q;
19 vector<ll> dis;
20 int n, ne = 0, a[maxn], c[maxn];
21 ll d[maxn];
22 
23 inline void add_edge(int f, int to, int d){
24     e[ne].to = to, e[ne].d = d;
25     e[ne].next = head[f];
26     head[f] = e + ne ++;
27 }
28 
29 void dfs(int u){
30     for (Edge * p = head[u]; p; p = p -> next){
31         d[p -> to] = d[u] + (ll)p -> d;
32         dfs(p -> to);
33     }
34 }
35 
36 void solve(int u){
37     c[u] = 1;
38     q.push_back(u);
39     dis.push_back(d[u]);
40 
41     int anc = lower_bound(dis.begin(), dis.end(), d[u] - (ll)a[u]) - dis.begin();
42 
43     if (anc >= 1)
44         c[q[anc - 1]] --;
45 
46     for (Edge * p = head[u]; p; p = p -> next){
47         solve(p -> to);
48         c[u] += c[p -> to];
49     }
50 
51     q.pop_back();
52     dis.pop_back();
53 }
54 
55 int main(){
56 #ifndef ONLINE_JUDGE
57     freopen(PRON ".in", "r", stdin);
58 #endif
59 
60     scanf("%d", &n);
61     for (int i = 1; i <= n; i ++)
62         scanf("%d", &a[i]);
63 
64     int fa, dis;
65     for (int i = 2; i <= n; i ++){
66         scanf("%d %d", &fa, &dis);
67         add_edge(fa, i, dis);
68     }
69 
70     d[1] = 0;
71     dfs(1);
72     solve(1);
73 
74     for (int i = 1; i <= n; i ++)
75         printf("%d ", c[i] - 1);
76     printf("\n");
77 }
code by cj

 

E. Alyona and towers

Problems:给一个数列a,每次操作让[l, r]上的数增加的,每次操作后求满足al < al + 1 < al + 2 < ... < ak > ak + 1 > ak + 2 > ... > ar的最大区间长度。

Analysis:

  cj:把数列换成差,这样的话每次区间修改操作,因为区间中的差是不变的,只有diff(arr[l - 1], arr[l])增加了d,diff(arr[r], arr[r + 1])减少了d,所以就变成了修改两个点的操作。用线段树维护一下就好了。不过要注意一下int要爆炸...并且要特判n = 1的情况。

Tags: Data structure

  1 #define PRON "740e"
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 #define inf 0x3f3f3f3f
  7 #define ls root << 1
  8 #define rs root << 1 | 1
  9 #define mid ((l + r) >> 1)
 10 #ifdef UNIX
 11 #define LL "%lld"
 12 #else
 13 #define LL "%I64d"
 14 #endif
 15 using namespace std;
 16 typedef long long ll;
 17 
 18 const int maxn = 3e5 + 10;
 19 
 20 struct node {
 21     int lans, rans, ans;
 22 } t[maxn << 2];
 23 
 24 int n, m;
 25 ll arr[maxn], a[maxn];
 26 
 27 void push_up(int l, int r, int root){
 28     t[root].ans = max(t[ls].ans, t[rs].ans);
 29     t[root].lans = t[ls].lans;
 30     t[root].rans = t[rs].rans;
 31 
 32     if ((a[mid] > 0 && a[mid + 1] != 0) || (a[mid] < 0 && a[mid + 1] < 0)){
 33         t[root].ans = max(t[root].ans, t[ls].rans + t[rs].lans);
 34         if (mid - l + 1 == t[ls].lans)
 35             t[root].lans = t[ls].lans + t[rs].lans;
 36         if (r - mid == t[rs].rans)
 37             t[root].rans = t[ls].rans + t[rs].rans;
 38     }
 39 }
 40 
 41 void build_tree(int l, int r, int root){
 42     if (l == r){
 43         t[root].ans = t[root].lans = t[root].rans = a[l] ? 1 : 0;
 44         return;
 45     }
 46 
 47     build_tree(l, mid, ls);
 48     build_tree(mid + 1, r, rs);
 49 
 50     push_up(l, r, root);
 51 }
 52 
 53 void update(int l, int r, int pos, int root){
 54     if (l == r && l == pos){
 55         t[root].ans = t[root].lans = t[root].rans = a[l] ? 1 : 0;
 56         return;
 57     }
 58 
 59     if (l <= pos && pos <= mid)
 60         update(l, mid, pos, ls);
 61     else
 62         update(mid + 1, r, pos, rs);
 63 
 64     push_up(l, r, root);
 65 }
 66 
 67 int main(){
 68 #ifndef ONLINE_JUDGE
 69     freopen(PRON ".in", "r", stdin);
 70 #endif
 71 
 72     scanf("%d", &n);
 73     for (int i = 0; i < n; i ++){
 74         scanf(LL, &arr[i]);
 75         if (i)
 76             a[i] = arr[i] - arr[i - 1];
 77     }
 78 
 79     if (n != 1)
 80     build_tree(1, n - 1, 1);
 81 
 82     int l, r, d;
 83     scanf("%d", &m);
 84     while (m --){
 85         scanf("%d %d %d", &l, &r, &d);
 86         if (n == 1){
 87             printf("1\n");
 88             continue;
 89         }
 90         if (l > 1){
 91             a[l - 1] += d;
 92             update(1, n - 1, l - 1, 1);
 93         }
 94         if (r < n){
 95             a[r] -= d;
 96             update(1, n - 1, r, 1);
 97         }
 98 
 99         printf("%d\n", t[1].ans + 1);
100     }
101 }
code by cj

 

Posted on 2017-01-25 13:58  Recluse_Team  阅读(175)  评论(0编辑  收藏  举报