题目链接 Codeforces_Gym_101485
Problem A
直接用优先队列进行贪心即可


1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include<string> 8 #include<set> 9 #include 10 #include
Problem B
比赛时居然现场没人开这道题
其实就是一个简单的dp
先要把所有包含的全部删除
f[i][j]代表前i个人分成j组的最大值
f[i][j] = max(f[i][j], f[k- 1][j - 1] + h[k].b - h[k].a)
排序后枚举k进行简单的转移即可
最后统计一下答案
——hnqw1214
……其实也不简单
这道题关键就是要想到把些时间段包含别人的人全部扔出来,放到另外一个地方。
去重蛮难想的,QW写的。
最后还要和之前的状态混合枚举一下。


1 #include2 3 using namespace std; 4 5 #define rep(i, a, b) for (int i(a); i <= (b); ++i) 6 #define dec(i, a, b) for (int i(a); i >= (b); --i) 7 #define fi first 8 #define se second 9 10 struct ss 11 { 12 int a,b; 13 }; 14 ss g[210], h[210]; 15 ss d[210]; 16 int n,p; 17 bool contain(ss a,ss b){ 18 return a.a<=b.a&&a.b>=b.b; 19 } 20 21 bool b[1010]; 22 23 int f[203][203]; 24 int ans = 0; 25 int et = 0; 26 27 bool cmp(const ss &a, const ss &b){ 28 return a.b - a.a > b.b - b.a; 29 } 30 31 bool cmp1(const ss &a, const ss &b){ 32 return a.a < b.a; 33 } 34 35 int main() 36 { 37 38 scanf("%d%d",&n,&p); 39 int i,j; 40 for (i=1;i<=n;i++) 41 scanf("%d%d",&g[i].a,&g[i].b); 42 int cnt=0; 43 for (i=1;i ) 44 for (j=i+1;j<=n;j++) 45 { 46 if (contain(g[i],g[j])) 47 b[i]=true; 48 else if (contain(g[j],g[i])) 49 b[j]=true; 50 } 51 52 53 for (i=1;i<=n;i++) if (!b[i]) h[++cnt]=g[i]; 54 55 sort(h + 1, h + cnt + 1, cmp1); 56 57 58 // printf("%d\n", cnt); 59 // rep(i, 1, cnt) printf("%d %d\n", h[i].a, h[i].b); 60 61 rep(i, 1, n) if (b[i]) d[++et] = g[i]; 62 63 sort(d + 1, d + et + 1, cmp); 64 65 rep(i, 0, cnt) rep(j, 0, p) f[i][j] = -(1e9 + 10000); 66 f[0][0] = 0; 67 rep(k, 1, p){ 68 rep(i, 1, cnt){ 69 rep(j, 1, i){ 70 if (h[j].b - h[i].a <= 0) continue; 71 f[i][k] = max(f[i][k], f[j - 1][k - 1] + h[j].b - h[i].a); 72 } 73 } 74 } 75 76 77 // ans = f[cnt][p]; 78 int ff = 0; 79 rep(i, 0, p){ 80 ff = ff + d[i].b - d[i].a; 81 if (p >= i) ans = max(ans, ff + f[cnt][p - i]); 82 } 83 84 printf("%d\n", ans); 85 86 87 88 }
Problem C
首先预处理一下哪些线段是相交的
然后把每条线段看成一个点
如果线段相交就连一条边
判断一下这张图是否是二分图


1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include<string> 8 #include 9 #include
Problem D
根据题意进行记忆化搜索


1 #include2 3 using namespace std; 4 5 #define rep(i, a, b) for (int i(a); i <= (b); ++i) 6 #define dec(i, a, b) for (int i(a); i >= (b); --i) 7 8 typedef long long LL; 9 10 const int N = 1e6 + 10; 11 12 LL n, r, p; 13 LL f[N]; 14 15 LL dp(LL n){ 16 if (n <= 1) return 0; 17 if (~f[n]) return f[n]; 18 LL ret = 6e18; 19 for (LL i = 2;i <= n; i++) ret = min(ret, dp((n - 1) / i + 1) + (i - 1) * p + r); 20 return f[n] = ret; 21 } 22 23 int main(){ 24 25 scanf("%lld%lld%lld", &n, &r, &p); 26 memset(f, -1, sizeof f); 27 printf("%lld\n", dp(n)); 28 return 0; 29 }
Problem E
构造二分图
把所有的算式看成一个点集
所有的答案看成一个点集
如果算式可以得到该答案就连边
然后求二分图的最大匹配


1 #include2 using namespace std; 3 typedef long long ll; 4 struct ss 5 { 6 ll x,y; 7 } a[2510]; 8 unordered_map mat,used; 9 ll result[2521],fuhao[2521],n; 10 bool crosspath(int k) 11 { 12 ll j=a[k].x+a[k].y; 13 if (!used[j]) 14 { 15 used[j]=1; 16 if (mat[j]==0||crosspath(mat[j])) 17 { 18 mat[j]=k; 19 result[k]=j; 20 fuhao[k]=0; 21 return true; 22 } 23 } 24 j=a[k].x-a[k].y; 25 if (!used[j]) 26 { 27 used[j]=1; 28 if (mat[j]==0||crosspath(mat[j])) 29 { 30 mat[j]=k; 31 result[k]=j; 32 fuhao[k]=1; 33 return true; 34 } 35 } 36 j=a[k].x*a[k].y; 37 if (!used[j]) 38 { 39 used[j]=1; 40 if (mat[j]==0||crosspath(mat[j])) 41 { 42 mat[j]=k; 43 result[k]=j; 44 fuhao[k]=2; 45 return true; 46 } 47 } 48 return false; 49 } 50 int main() 51 { 52 scanf("%lld",&n); 53 int i; 54 for (i=1;i<=n;i++) 55 scanf("%lld%lld",&a[i].x,&a[i].y); 56 int match=0; 57 for (i=1;i<=n;i++) 58 { 59 if (crosspath(i)) 60 match++; 61 used.clear(); 62 } 63 if (match<n) 64 puts("impossible"); 65 else 66 { 67 for (i=1;i<=n;i++) 68 { 69 printf("%lld ",a[i].x); 70 if (fuhao[i]==0) printf("+ "); 71 else if (fuhao[i]==1) printf("- "); 72 else printf("* "); 73 printf("%lld ",a[i].y); 74 printf("= "); 75 printf("%lld\n",result[i]); 76 } 77 } 78 return 0; 79 }
Problem F
Problem G
其实就是一个三维偏序问题
用cdq分治求解即可
(模板题哦)


1 #include2 3 using namespace std; 4 5 #define rep(i, a, b) for (int i(a); i <= (b); ++i) 6 #define dec(i, a, b) for (int i(a); i >= (b); --i) 7 8 typedef long long LL; 9 10 const int N = 1e6 + 10; 11 12 struct Node 13 { 14 int x, y, z, f, cnt; 15 void read() { f = 0; } 16 bool operator < (const Node &rhs) const 17 { 18 if (x != rhs.x) return x < rhs.x; 19 if (y != rhs.y) return y < rhs.y; 20 return z < rhs.z; 21 } 22 bool operator == (const Node &rhs) const 23 { return x == rhs.x && y == rhs.y && z == rhs.z; } 24 } 25 26 a[N], b[N]; 27 28 29 int n, st[N<<1], ans[N]; 30 31 void init(){ 32 sort(a + 1, a + n + 1); 33 int sz = 0; 34 for (int i = 1; i <= n; ++i) 35 { 36 b[++sz] = a[i]; b[sz].cnt = 1; int j = i; 37 while (j < n && a[j + 1] == a[j]) { ++j; b[sz].cnt++;} 38 i = j; 39 } 40 n = sz; 41 memset(st, 0, sizeof st); 42 } 43 44 void add(int k, int num){ 45 while (k <= n) 46 { 47 st[k] += num; 48 k += k & (-k); 49 } 50 } 51 int query(int k){ 52 int ans = 0; 53 while (k){ 54 ans += st[k]; 55 k -= k & (-k); 56 } 57 return ans; 58 } 59 60 void cdq(int l, int r){ 61 if (l == r) return; 62 int mid = l + r >> 1; 63 cdq(l, mid); 64 cdq(mid + 1, r); 65 int i = l, j = mid + 1; 66 for (int p = l; p <= r; ++p) 67 { 68 if (i <= mid && (j > r || b[i].y <= b[j].y)) 69 { 70 add(b[i].z, b[i].cnt); 71 a[p] = b[i++]; 72 } else { 73 b[j].f += query(b[j].z); 74 a[p] = b[j++]; 75 } 76 } 77 for (int i = l; i <= mid; ++i) 78 add(b[i].z, -b[i].cnt); 79 for (int i = l; i <= r; ++i) 80 b[i] = a[i]; 81 } 82 83 int main(){ 84 85 scanf("%d", &n); 86 rep(i, 1, n){ 87 int x; 88 scanf("%d", &x); 89 a[x].x = i; 90 } 91 92 rep(i, 1, n){ 93 int x; 94 scanf("%d", &x); 95 a[x].y = i; 96 } 97 98 rep(i, 1, n){ 99 int x; 100 scanf("%d", &x); 101 a[x].z = i; 102 } 103 104 // rep(i, 1, n) printf("%d %d %d\n", a[i].x, a[i].y, a[i].z); 105 106 107 int sav = n; 108 init(); 109 cdq(1, n); 110 LL ret = 0; 111 for (int i = 1; i <= n; ++i) ret += (LL)b[i].f; 112 printf("%lld\n", ret); 113 return 0; 114 }
Problem H
Problem I
根据题意进行模拟
不断地更新x,y的值即可


1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include<string> 8 #include 9 #include
Problem J
直接可以预处理出所有答案


1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include<string> 8 #include<set> 9 #include 10 #include
Problem K
题目看似比较复杂
其实是一个简单的计数原理
因为每顿餐都最多只有25种
所以可以直接枚举每种搭配
求出每种搭配要用到的佐料
用乘法原理进行统计
为防止溢出,在进行乘法计算时可以用除法先判断一下是否越界


1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include<string> 8 #include 9 #include