A:Alphabet
Solved.
签。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 char s[60]; 4 int f[60]; 5 int main(){ 6 scanf("%s",s+1); 7 int n=strlen(s+1); 8 for(int i=1;i<=n;i++) 9 { 10 f[i]=1; 11 } 12 for(int i=2;i<=n;i++) 13 { 14 for(int j=1;j<i;j++) 15 { 16 if(s[i]>s[j]){ 17 f[i]=max(f[i],f[j]+1); 18 } 19 } 20 } 21 int maxn=0; 22 for(int i=1;i<=n;i++) 23 { 24 maxn=max(maxn,f[i]); 25 } 26 cout<<26-maxn<<endl; 27 }
B:Buggy Robot
Solved.
题意:
给出一个地图,从'R' 走到 'E' , 可以增加或者删除机器人的指令
求最少的修改次数,使得机器人可以到达'E'
思路:
搜索。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 50 + 10; 6 const int INF = 0x3f3f3f3f; 7 8 struct node{ 9 int x, y; 10 int step; 11 node(){} 12 node(int x, int y, int step): x(x), y(y), step(step){}; 13 }; 14 15 int n, m; 16 int sx, sy, ex, ey; 17 int len; 18 char mp[maxn][maxn]; 19 char op[maxn * maxn]; 20 int dis[maxn][maxn][maxn * maxn]; 21 int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1}; 22 23 bool judge(int x,int y) 24 { 25 if(x < 1 || x > n || y < 1 || y > m || mp[x][y] == '#') return false; 26 else return true; 27 } 28 29 void BFS() 30 { 31 queue<node>q; 32 q.push(node(sx, sy, 0)); 33 dis[sx][sy][0] = 0; 34 while(!q.empty()) 35 { 36 node st = q.front(); 37 q.pop(); 38 //not do 39 if(st.step + 1 <= len) 40 { 41 node now = st; 42 now.step++; 43 if(dis[st.x][st.y][st.step] + 1 < dis[now.x][now.y][now.step]) 44 { 45 dis[now.x][now.y][now.step] = dis[st.x][st.y][st.step] + 1; 46 q.push(now); 47 } 48 } 49 //do 50 if(st.step + 1 <= len) 51 { 52 node now = st; 53 now.step++; 54 if(op[now.step] == 'U') 55 { 56 now.x--; 57 } 58 else if(op[now.step] == 'D') 59 { 60 now.x++; 61 } 62 else if(op[now.step] == 'L') 63 { 64 now.y--; 65 } 66 else if(op[now.step] == 'R') 67 { 68 now.y++; 69 } 70 if(!judge(now.x, now.y)) 71 { 72 now.x = st.x; 73 now.y = st.y; 74 } 75 if(dis[st.x][st.y][st.step] < dis[now.x][now.y][now.step]) 76 { 77 dis[now.x][now.y][now.step] = dis[st.x][st.y][st.step]; 78 q.push(now); 79 } 80 81 } 82 //add 83 node now = st; 84 for(int i = 0; i < 4; ++i) 85 { 86 now.x = st.x + dir[i][0]; 87 now.y = st.y + dir[i][1]; 88 if(judge(now.x, now.y)) 89 { 90 if(dis[st.x][st.y][st.step] + 1 < dis[now.x][now.y][now.step]) 91 { 92 dis[now.x][now.y][now.step] = dis[st.x][st.y][st.step] + 1; 93 q.push(now); 94 } 95 } 96 } 97 } 98 } 99 100 int main() 101 { 102 while(~scanf("%d %d", &n, &m)) 103 { 104 for(int i = 1; i <= n; ++i) 105 { 106 for(int j = 1; j <= m; ++j) 107 { 108 scanf(" %c", &mp[i][j]); 109 if(mp[i][j] == 'R'){ sx = i, sy = j; } 110 if(mp[i][j] == 'E'){ ex = i, ey = j; } 111 } 112 } 113 scanf("%s", op + 1); 114 len = strlen(op + 1); 115 memset(dis, 0x3f, sizeof dis); 116 BFS(); 117 int ans = INF; 118 for(int i = 1; i <= len; ++i) ans = min(ans, dis[ex][ey][i]); 119 printf("%d\n", ans); 120 } 121 return 0; 122 }
C:Cameras
Solved.
签。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int n, k, r, a[N]; 6 7 int main() 8 { 9 while (scanf("%d%d%d", &n, &k, &r) != EOF) 10 { 11 memset(a, 0, sizeof a); 12 for (int i = 1, x; i <= k; ++i) 13 { 14 scanf("%d", &x); 15 a[x] = 1; 16 } 17 int res = 0; 18 int tot = 0; 19 for (int i = 1; i <= r - 1; ++i) tot += a[i]; 20 for (int i = 1; i + r - 1<= n; ++i) 21 { 22 tot += a[i + r - 1]; 23 if (tot < 2) 24 { 25 for (int j = i + r - 1; j >= 1 && tot < 2; --j) if (!a[j]) 26 { 27 a[j] = 1; 28 ++tot; 29 ++res; 30 } 31 } 32 tot -= a[i]; 33 } 34 printf("%d\n", res); 35 } 36 return 0; 37 }
D:Contest Strategy
Unsolved.
题意:
在一场ICPC比赛中,有一个人知道它解决每道题需要多少时间
但是必须要先读这道题,才能做
做题策略是
开场先随机读k道题,然后按做题时间放入小根堆
每次取堆顶出来做,每做一道题,就随机再读一题(如果还有题目可以读)
求$\;N!\;种读题顺序的所有罚时加起来 MOD\;\; 1e\;9 +7$
E:Enclosure
Unsolved.
F:Illumination
Solved.
题意:
有一个矩形,在某些点有灯泡,可以选择照亮当前行或者照亮当前列
每个灯泡照亮的范围相同为$r$
但是同行或者同列的照亮不能相交
求有没有一种方案使得所有灯泡都可以打开
思路:
一个点拆成两个点,表示照亮行或列
然后建边,丢进2-sat跑一跑即可
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 #define N 2010 5 int n, r, l; 6 struct Graph 7 { 8 struct node 9 { 10 int to, nx; 11 node () {} 12 node (int to, int nx) : to(to), nx(nx) {} 13 }a[N * N * 2]; 14 int head[N], pos; 15 void init() 16 { 17 memset(head, -1, sizeof head); 18 pos = 0; 19 } 20 void add(int u, int v) { a[++pos] = node(v, head[u]); head[u] = pos; } 21 }G; 22 #define erp(u) for (int it = G.head[u], v = G.a[it].to; ~it; it = G.a[it].nx, v = G.a[it].to) 23 int x[N], y[N]; 24 // 0 x 1 y 25 26 bool vis[N]; 27 int S[N], top; 28 bool DFS(int u) 29 { 30 if (vis[u ^ 1]) return false; 31 if (vis[u]) return true; 32 vis[u] = 1; 33 S[top++] = u; 34 erp (u) if (!DFS(v)) return false; 35 return true; 36 } 37 38 bool twosat(int n) 39 { 40 memset(vis, 0, sizeof vis); 41 for (int i = 0; i < n; i += 2) 42 { 43 if (vis[i] || vis[i ^ 1]) continue; 44 top = 0; 45 if (!DFS(i)) 46 { 47 while (top) vis[S[--top]] = false; 48 if (!DFS(i ^ 1)) return false; 49 } 50 } 51 return true; 52 } 53 54 int main() 55 { 56 while (scanf("%d%d%d", &n, &r, &l) != EOF) 57 { 58 G.init(); 59 for (int i = 0; i < l; ++i) scanf("%d%d", x + i, y + i); 60 for (int i = 0; i < l; ++i) for (int j = i + 1; j < l; ++j) 61 { 62 if (x[i] == x[j] && abs(y[i] - y[j]) <= 2 * r) 63 { 64 G.add(i << 1, j << 1 | 1); 65 G.add(j << 1, i << 1 | 1); 66 } 67 if (y[i] == y[j] && abs(x[i] - x[j]) <= 2 * r) 68 { 69 G.add(i << 1 | 1, j << 1); 70 G.add(j << 1 | 1, i << 1); 71 } 72 } 73 puts(twosat(2 * l) ? "YES" : "NO"); 74 } 75 return 0; 76 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 2e3 + 10; 6 7 struct node{ 8 int x, y; 9 node(){} 10 node(int x,int y): x(x), y(y){} 11 }arr[maxn]; 12 13 struct Edge{ 14 int to, nxt; 15 Edge(){} 16 Edge(int to, int nxt) : to(to), nxt(nxt){} 17 }edge[(maxn * maxn) << 2]; 18 19 int head[maxn << 1], tot, vis[maxn << 1]; 20 21 void Init() 22 { 23 tot = 0; 24 memset(head, -1, sizeof head); 25 memset(vis, 0, sizeof vis); 26 } 27 28 void addedge(int u, int v, int val) 29 { 30 int tmpu = u * 2 + val; 31 int tmpv = v * 2 + val; 32 edge[tot] = Edge(tmpv, head[tmpu ^ 1]); head[tmpu ^ 1] = tot++; 33 edge[tot] = Edge(tmpu, head[tmpv ^ 1]); head[tmpv ^ 1] = tot++; 34 } 35 36 int n, r, l; 37 int S[maxn << 1], top; 38 39 bool DFS(int u) 40 { 41 if(vis[u ^ 1]) return false; 42 if(vis[u]) return true; 43 vis[u]++; 44 S[top++] = u; 45 for(int i = head[u]; ~i; i = edge[i].nxt) 46 { 47 if(!DFS(edge[i].to)) return false; 48 } 49 return true; 50 } 51 52 bool solve() 53 { 54 for(int i = 0; i < (l << 1); i += 2) 55 { 56 if(vis[i] == 0 && vis[i ^ 1] == 0) 57 { 58 top = 0; 59 if(!DFS(i)) 60 { 61 while(top) vis[S[--top]] = 0; 62 if(!DFS(i ^ 1)) return false; 63 } 64 } 65 } 66 return true; 67 68 } 69 70 int main() 71 { 72 while(~scanf("%d %d %d", &n, &r, &l)) 73 { 74 Init(); 75 for(int i = 0; i < l; ++i) scanf("%d %d", &arr[i].x, &arr[i].y); 76 for(int i = 0; i < l; ++i) 77 { 78 for(int j = 0; j < i; ++j) 79 { 80 if(arr[i].y == arr[j].y && abs(arr[i].x - arr[j].x) <= 2 * r) 81 { 82 addedge(i, j, 0); 83 } 84 if(arr[i].x == arr[j].x && abs(arr[i].y - arr[j].y) <= 2 * r) 85 { 86 addedge(i, j, 1); 87 } 88 } 89 } 90 puts(solve() ? "YES" : "NO"); 91 } 92 return 0; 93 }
G:Maximum Islands
Unsolved.
题意:
有一张卫星图,可以看到陆地上有些地方是海洋,有些地方是陆地
陆地的连通块是岛屿,也有些地方看到的是云朵
云朵下面可以是陆地也可以是海洋
求岛屿的最大数量
H:Paint
Solved.
题意:
给出一些区间,求选出任意个数的区间,使得这些区间不相交
并且区间并最大,输出n - 区间并
思路:
类似于最长上升子序列,一个区间的左端点要接在所有右端点小于它的所有区间中的最大值即可
树状数组维护一下就没了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 200010 6 ll n, b[N << 2]; 7 int k, m; 8 struct qnode 9 { 10 ll l, r; 11 void scan() { scanf("%lld%lld", &l, &r); } 12 bool operator < (const qnode &other) const { return r < other.r || r == other.r && l < other.l; } 13 }q[N]; 14 15 void Hash() 16 { 17 m = 0; 18 for (int i = 1; i <= k; ++i) 19 { 20 b[++m] = q[i].l; 21 b[++m] = q[i].r; 22 } 23 sort(b + 1, b + 1 + m); 24 m = unique(b + 1, b + 1 + m) - b - 1; 25 for (int i = 1; i <= k; ++i) 26 { 27 q[i].l = lower_bound(b + 1, b + 1 + m, q[i].l) - b; 28 q[i].r = lower_bound(b + 1, b + 1 + m, q[i].r) - b; 29 } 30 } 31 32 namespace BIT 33 { 34 ll a[N << 2]; 35 void update(int x, ll val) 36 { 37 for (; x < (N << 2); x += x & -x) 38 a[x] = max(a[x], val); 39 } 40 ll query(int x) 41 { 42 ll res = 0; 43 for (; x; x -=x & -x) 44 res = max(res, a[x]); 45 return res; 46 } 47 } 48 49 int main() 50 { 51 while (scanf("%lld%d", &n, &k) != EOF) 52 { 53 for (int i = 1; i <= k; ++i) q[i].scan(); Hash(); 54 sort(q + 1, q + 1 + k); 55 ll res = 0; 56 for (int i = 1; i <= k; ++i) 57 { 58 ll tmp = BIT::query(q[i].l - 1); 59 tmp += b[q[i].r] - b[q[i].l] + 1; 60 res = max(res, tmp); 61 BIT::update(q[i].r, tmp); 62 } 63 printf("%lld\n", n - res); 64 } 65 return 0; 66 }
I:Postman
Solved.
题意:
有n个房子,每个放在位于$x_i点$邮局在0点,每个房子有$m_i封信要送$
只有一个邮递员,每次最多携带$k_i封信,求邮递员最少的路程$
思路:
负的和正的分开做
每次都先跑最远的,如果可以携带多余的信,就给次远的,再给次次远的。
贪心做一下就没了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 1010 6 ll res; 7 int n, m, k; 8 int x[N], v[N]; 9 10 struct node 11 { 12 int x, v; 13 node () {} 14 node (int x, int v) : x(x), v(v) {} 15 bool operator < (const node &r) const { return x < r.x; } 16 }q[N]; 17 18 void solve() 19 { 20 sort(q + 1, q + 1 + m); 21 for (int i = m; i >= 1; --i) 22 { 23 res += 2ll * (q[i].v / k) * q[i].x; 24 int remind = q[i].v % k; 25 if (remind) 26 { 27 remind = k - remind; 28 res += 2ll * q[i].x; 29 for (int j = i - 1; j >= 1; --j) 30 { 31 if (remind >= q[j].v) 32 { 33 remind -= q[j].v; 34 q[j].v = 0; 35 } 36 else 37 { 38 q[j].v -= remind; 39 break; 40 } 41 } 42 } 43 } 44 } 45 46 int main() 47 { 48 while (scanf("%d%d", &n, &k) != EOF) 49 { 50 for (int i = 1; i <= n; ++i) scanf("%d%d", x + i, v + i); 51 res = 0; m = 0; 52 for (int i = 1; i <= n; ++i) if (x[i] < 0) q[++m] = node(-x[i], v[i]); 53 solve(); 54 m = 0; 55 for (int i = 1; i <= n; ++i) if (x[i] > 0) q[++m] = node(x[i], v[i]); 56 solve(); 57 printf("%lld\n", res); 58 } 59 return 0; 60 }
j:Shopping
Solved.
题意:
有一个超市,$有n种物品,每种物品a_i元,每种物品无限个$
$q次询问,每次询问从第l_i个商品走到第r_i个商品,身上有v_i块钱,能买则买,问最后剩下多少钱$
思路:
每次购买一个物品那么手中的钱至少缩小一半
最多需要购买log种物品
再二分查找最近的小于自己的物品
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 200010 6 int n, q; 7 ll a[N]; 8 9 ll dp[N][20]; 10 int mm[N]; 11 void init(int n, ll b[]) 12 { 13 mm[0] = -1; 14 for (int i = 1; i <= n; ++i) 15 { 16 mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1: mm[i - 1]; 17 dp[i][0] = b[i]; 18 } 19 for (int j = 1; j <= mm[n]; ++j) 20 for (int i = 1; i + (1 << j) - 1 <= n; ++i) 21 dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); 22 } 23 24 ll query(int l, int r) 25 { 26 int k = mm[r - l + 1]; 27 return min(dp[l][k], dp[r - (1 << k) + 1][k]); 28 } 29 30 int main() 31 { 32 while (scanf("%d%d", &n, &q) != EOF) 33 { 34 for (int i = 1; i <= n; ++i) scanf("%lld", a + i); init(n, a); 35 ll v; 36 for (int i = 1, l, r; i <= q; ++i) 37 { 38 scanf("%lld%d%d", &v, &l, &r); 39 while (r - l >= 0) 40 { 41 int ql = l, qr = r, tar = -1; 42 while (qr - ql >= 0) 43 { 44 int mid = (ql + qr) >> 1; 45 if (query(ql, mid) <= v) 46 { 47 qr = mid - 1; 48 tar = mid; 49 } 50 else 51 ql = mid + 1; 52 } 53 if (tar == -1) break; 54 v %= a[tar]; 55 l = tar + 1; 56 } 57 printf("%lld\n", v); 58 } 59 } 60 return 0; 61 }
K:Tournament Wins
Solved.
题意:
有$2^k个玩家,进行对局,rank小的一定能打败\;\;rank\;\;大的$
如果你$rank = r 那么求出你在一轮游戏中赢的局数的期望$
一轮游戏为每次两两对战,输的离开,赢得剩下继续对战,直到只有一个人
思路:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = (1 << 20) + 10; 5 const double EXP = exp(1.0); 6 7 double fac[maxn]; 8 9 void Init() 10 { 11 fac[0] = 0; 12 for(int i = 1; i < maxn; ++i) fac[i] = fac[i - 1] + log(i); 13 } 14 15 int k, r; 16 17 int main() 18 { 19 Init(); 20 while(~scanf("%d %d", &k, &r)) 21 { 22 double ans = 0; 23 int limit = 1 << k; 24 for(int i = 1; i <= k; ++i) 25 { 26 int m = (1 << i); 27 if(limit - r - m + 1 < 0) break; 28 ans += exp((fac[limit - r] - fac[limit - r - m + 1]) - (fac[limit - 1] - fac[limit - m])); 29 } 30 printf("%.5f\n", ans); 31 } 32 return 0; 33 }
L:Windy Path
Unsolved.