题目链接:https://codeforc.es/contest/1076
A. Minimizing the String
题意:给出一个字符串,最多删掉一个字母,输出操作后字典序最小的字符串。
题解:若存在一个位置 i 满足 a[i] > a[i+1],若不删除 a[i] 则后续操作不可能更优。

1 #include <bits/stdc++.h>
2 using namespace std;
3 #define ll long long
4 #define ull unsigned long long
5 #define mst(a,b) memset((a),(b),sizeof(a))
6 #define mp(a,b) make_pair(a,b)
7 #define pi acos(-1)
8 #define pii pair<int,int>
9 #define pb push_back
10 const int INF = 0x3f3f3f3f;
11 const double eps = 1e-6;
12 const int MAXN = 2e5 + 10;
13 const int MAXM = 2e5 + 10;
14 const ll mod = 1e9 + 7;
15
16 char s[MAXN];
17
18 int main() {
19 #ifdef local
20 freopen("data.txt", "r", stdin);
21 // freopen("data.txt", "w", stdout);
22 #endif
23 int n;
24 scanf("%d%s",&n,s);
25 int pos = n - 1;
26 for(int i = 0; i < n - 1; i++) {
27 if(s[i] > s[i + 1]) {
28 pos = i;
29 break;
30 }
31 }
32 for(int i = 0; i < n; i++)
33 if(i != pos) printf("%c",s[i]);
34 return 0;
35 }
B. Divisor Subtraction
题意:对于一个 n,每次减去它的最小质因子直到为 0,求操作次数。
题解:n <= 1e10,所以先筛出 1e5 以内的质因子,然后暴力找最小质因子,当最小质因子为 2 的时候,已经不存在更小的质因子,直接跳出循环即可。

1 #include <bits/stdc++.h>
2 using namespace std;
3 #define ll long long
4 #define ull unsigned long long
5 #define mst(a,b) memset((a),(b),sizeof(a))
6 #define mp(a,b) make_pair(a,b)
7 #define pi acos(-1)
8 #define pii pair<int,int>
9 #define pb push_back
10 const int INF = 0x3f3f3f3f;
11 const double eps = 1e-6;
12 const int MAXN = 2e5 + 10;
13 const int MAXM = 2e5 + 10;
14 const ll mod = 1e9 + 7;
15
16 bool check[MAXN];
17 int prime[MAXN];
18 int tot;
19
20 void init() {
21 mst(check, false);
22 tot = 0;
23 for(int i = 2; i <= 1e5; i++) {
24 if(!check[i]) prime[tot++] = i;
25 for(int j = 0; j < tot; j++) {
26 if(i * prime[j] > 1e5) break;
27 check[i * prime[j]] = true;
28 if(i % prime[j] == 0) break;
29 }
30 }
31 }
32
33 int main() {
34 #ifdef local
35 freopen("data.txt", "r", stdin);
36 // freopen("data.txt", "w", stdout);
37 #endif
38 init();
39 ll n;
40 scanf("%lld",&n);
41 ll ans = 0;
42 while(n) {
43 bool flag = false;
44 for(int i = 0; i < tot && n >= prime[i]; i++) {
45 if(n % prime[i] == 0) {
46 if(prime[i] == 2) {
47 flag = true;
48 ans += n / 2;
49 n = 0;
50 break;
51 }
52 n -= prime[i];
53 ans++;
54 flag = true;
55 break;
56 }
57 }
58 if(!flag) {
59 ans++;
60 break;
61 }
62 }
63 printf("%lld\n",ans);
64 return 0;
65 }
C. Meme Problem
题意:给出一个 d,求是否存在 a + b = d 且 ab = d。
题解:解一元二次方程,判一下无解的条件即可。

1 #include <bits/stdc++.h>
2 using namespace std;
3 #define ll long long
4 #define ull unsigned long long
5 #define mst(a,b) memset((a),(b),sizeof(a))
6 #define mp(a,b) make_pair(a,b)
7 #define pi acos(-1)
8 #define pii pair<int,int>
9 #define pb push_back
10 const int INF = 0x3f3f3f3f;
11 const double eps = 1e-6;
12 const int MAXN = 2e5 + 10;
13 const int MAXM = 2e5 + 10;
14 const ll mod = 1e9 + 7;
15
16
17
18 int main() {
19 #ifdef local
20 freopen("data.txt", "r", stdin);
21 // freopen("data.txt", "w", stdout);
22 #endif
23 int t;
24 cin >> t;
25 while(t--) {
26 int d;
27 cin >> d;
28 if(d < 4 && d != 0) {
29 cout << "N" << endl;
30 continue;
31 }
32 cout << "Y ";
33 long double a = sqrt(((long double)d * d - 4.0 * (long double)d) / 4.0) + (long double)d / 2.0;
34 long double b = (long double)d - a;
35 cout << fixed << setprecision(10) << a << ' ';
36 cout << fixed << setprecision(10) << b << endl;
37 }
38 return 0;
39 }
D. Edge Deletion
题意:给出一个 n 个点 m 条边的图,问最多保留 k 条边的情况下,起点 1 到每个点的最短路不变的最多有多少个,输出保留的边。
题解:先对起点 1 跑一遍 dij,因为 n - 1 条边可以构成图的最短路,每条边产生对一个点的最短路,故跑 dij 时记录一下走当前这个点的边,跑 dfs 按顺序输出结果即可。

1 #include <bits/stdc++.h>
2 using namespace std;
3 #define ll long long
4 #define ull unsigned long long
5 #define mst(a,b) memset((a),(b),sizeof(a))
6 #define mp(a,b) make_pair(a,b)
7 #define pi acos(-1)
8 #define pii pair<int,int>
9 #define pb push_back
10 const int INF = 0x3f3f3f3f;
11 const double eps = 1e-6;
12 const int MAXN = 3e5 + 10;
13 const int MAXM = 2e5 + 10;
14 const ll mod = 1e9 + 7;
15
16
17 struct edge {
18 int v,w,id;
19 };
20
21 vector<edge>g[MAXN];
22 bool vis[MAXN];
23 ll dis[MAXN];
24 vector<int>ans;
25 pii add[MAXN];
26
27 void dij(int s, int n) {
28 ll inf2 = 1e16;
29 for(int i = 1; i <= n; ++i)
30 dis[i] = inf2, vis[i] = 0;
31 dis[s] = 0;
32 priority_queue<pair<ll, int> >q;
33 q.push(mp(0, s));
34 for(; !q.empty();) {
35 int u = q.top().second;
36 q.pop();
37 if(vis[u]) continue;
38 vis[u] = 1;
39 for(int j = 0, sz = g[u].size(); j < sz; ++j) {
40 int v = g[u][j].v;
41 int w = g[u][j].w;
42 int id = g[u][j].id;
43 if(dis[v] > dis[u] + w) {
44 add[v] = mp(u,id);
45 dis[v] = dis[u] + w;
46 q.push(mp(-dis[v], v));
47 }
48 }
49 }
50 }
51
52 vector<pii>vec[MAXN];
53 int tot;
54
55 void dfs(int u) {
56 vis[u] = true;
57 for(int i = 0; i < vec[u].size() && tot; i++) {
58 int v = vec[u][i].first, id = vec[u][i].second;
59 if(vis[v]) continue;
60 printf("%d ",id);
61 tot--;
62 dfs(v);
63 }
64 }
65
66 int main() {
67 #ifdef local
68 freopen("data.txt", "r", stdin);
69 // freopen("data.txt", "w", stdout);
70 #endif
71 int n,m,k;
72 scanf("%d%d%d",&n,&m,&k);
73 for(int i = 1; i <= m; i++) {
74 int u,v,w;
75 scanf("%d%d%d",&u,&v,&w);
76 g[u].pb({v,w,i});
77 g[v].pb({u,w,i});
78 }
79 dij(1,n);
80 for(int i = 2; i <= n; i++) {
81 vec[i].push_back(mp(add[i].first,add[i].second));
82 vec[add[i].first].push_back(mp(i,add[i].second));
83 }
84 tot = min(n - 1,k);
85 printf("%d\n",min(n - 1,k));
86 mst(vis, false);
87 dfs(1);
88 return 0;
89 }
E. Vasya and a Tree
题意:有一棵 n 个点的树,有 m 次操作(v,d,x),每次将以 v 为根且距离 v <= d 的点加上权值 x(初始权值为0),输出最后每个点的权值。
题解:考虑离线操作,把每个点作为根的操作存起来,dfs 记录当前深度所增加的权值,对于不可到达的深度,用一个数组来记录要减去的值,差分的思想,详见代码~

1 #include <bits/stdc++.h>
2 using namespace std;
3 #define ll long long
4 #define ull unsigned long long
5 #define mst(a,b) memset((a),(b),sizeof(a))
6 #define mp(a,b) make_pair(a,b)
7 #define pi acos(-1)
8 #define pii pair<int,int>
9 #define pb push_back
10 const int INF = 0x3f3f3f3f;
11 const double eps = 1e-6;
12 const int MAXN = 3e5 + 10;
13 const int MAXM = 2e5 + 10;
14 const ll mod = 1e9 + 7;
15
16 vector<int>vec[MAXN];
17 vector<pii>q[MAXN];
18
19
20 int h = -1;
21 ll ans[MAXN],dep[MAXN],now = 0;
22
23 void dfs(int u,int fa) {
24 h++;
25 now += dep[h];
26 for(int i = 0; i < q[u].size(); i++) {
27 int d = q[u][i].first, x = q[u][i].second;
28 now += x;
29 if(h + d + 1 < MAXN) dep[h + d + 1] -= x;
30 }
31 // cout << u << " " << fa << ":" << now << endl;
32 ans[u] += now;
33 for(int i = 0; i < vec[u].size(); i++) {
34 int v = vec[u][i];
35 if(v == fa) continue;
36 dfs(v,u);
37 }
38 for(int i = 0; i < q[u].size(); i++) {
39 int d = q[u][i].first, x = q[u][i].second;
40 now -= x;
41 if(h + d + 1 < MAXN) dep[h + d + 1] += x;
42 }
43 now -= dep[h];
44 h--;
45 }
46
47 int main() {
48 #ifdef local
49 freopen("data.txt", "r", stdin);
50 // freopen("data.txt", "w", stdout);
51 #endif
52 int n;
53 scanf("%d",&n);
54 for(int i = 1; i < n; i++) {
55 int u,v;
56 scanf("%d%d",&u,&v);
57 vec[u].push_back(v);
58 vec[v].push_back(u);
59 }
60 int m;
61 scanf("%d",&m);
62 while(m--) {
63 int v,d,x;
64 scanf("%d%d%d",&v,&d,&x);
65 q[v].push_back(mp(d,x));
66 }
67 dfs(1,0);
68 for(int i = 1; i <= n; i++)
69 printf("%lld ",ans[i]);
70 return 0;
71 }
F. Summer Practice Report
题意:一本书有 n 页,每页有 xi 个 0 和 yi 个 1,问存不存在每页的数字构成一个序列,连起来之后最多连续的 0 和 1 不超过 k。
题解:记录每一页组成序列之后,连续 1 和连续 0 的最小值,转移即可。因为一页中连续的 1 最多 k 个,所以可容纳的 0 的个数为 pre0 + k * x,记录这个数是否大于 0 即可判断是否合法,1 也同理。

1 #include <bits/stdc++.h>
2 using namespace std;
3 #define ll long long
4 #define ull unsigned long long
5 #define mst(a,b) memset((a),(b),sizeof(a))
6 #define mp(a,b) make_pair(a,b)
7 #define pi acos(-1)
8 #define pii pair<int,int>
9 #define pb push_back
10 const int INF = 0x3f3f3f3f;
11 const double eps = 1e-6;
12 const int MAXN = 3e5 + 10;
13 const int MAXM = 2e5 + 10;
14 const ll mod = 1e9 + 7;
15
16 ll x[MAXN],y[MAXN];
17
18 int main() {
19 #ifdef local
20 freopen("data.txt", "r", stdin);
21 // freopen("data.txt", "w", stdout);
22 #endif
23 int n;
24 ll k;
25 scanf("%d%lld",&n,&k);
26 for(int i = 1; i <= n; i++) scanf("%lld",&x[i]);
27 for(int i = 1; i <= n; i++) scanf("%lld",&y[i]);
28 ll nowx = -k, nowy = -k;
29 for(int i = 1; i <= n; i++) {
30 nowx += x[i] - y[i] * k;
31 nowy += y[i] - x[i] * k;
32 if(nowx < -k) nowx = -k;
33 if(nowy < -k) nowy = -k;
34 if(nowx > 0 || nowy > 0) {
35 puts("NO");
36 return 0;
37 }
38 }
39 puts("YES");
40 return 0;
41 }
G. Array Game(待补)
题意:
题解:
来源:https://www.cnblogs.com/scaulok/p/9951217.html
