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
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
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
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
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