Codeforces Round 906 (Div. 2) A-E1

A. Doremy's Paint 3

记数组中数的种类数为k,当k=1时,答案为yes;当k=2时,记两个种类的数的个数差为d,当d1时,答案为yes;其他情况答案为no

时间复杂度:O(nlogn)

 1 void solve()
 2 {
 3     int n; cin >> n;
 4 
 5     map<int, int> mp;
 6     vector<int> a(n + 1);
 7     for (int i = 1; i <= n; i++) 
 8     {
 9         cin >> a[i];
10         mp[a[i]]++;
11     }
12     if (mp.size() == 1 || (mp.size() == 2 && abs(mp.begin()->sc - (--mp.end())->sc) <= 1)) cout << "YES\n";
13     else cout << "NO\n";
14 }

B. Qingshan Loves Strings

顺序遍历s,若遇到相邻两字符相等时,则尝试在他们中间加入t,若t本身不是好的或加入ts仍然是不好的(可以用t的首尾字符直接比较,不用真的加入),答案则为no;其他情况答案为yes

时间复杂度:O(n+m)

 1 void solve()
 2 {
 3     int n, m;
 4     cin >> n >> m;
 5 
 6     string s, t;
 7     cin >> s >> t;
 8 
 9     char f = t.front(), b = t.back();
10 
11     bool OK = true, used = false;
12     for (int i = 0; i < n - 1; i++)
13         if (s[i] == s[i + 1])
14         {
15             if (s[i] == f || s[i + 1] == b) OK = false;
16             else used = true;
17         }
18 
19     if (!OK) cout << "NO\n";
20     else if (!used) cout << "YES\n"; 
21     else  
22     {
23         for (int i = 0; i < m - 1; i++)
24             if (t[i] == t[i + 1])
25             {
26                 cout << "NO\n";
27                 return;
28             }
29 
30         cout << "YES\n";
31     }
32 }

C. Qingshan Loves Strings 2

n为奇数时,答案为1;当n为偶数时,记s当前的首字符为f,尾字符为b,当f=b时,若f=1,则在当前s的开头插入01,若f=0,则在当前s的结尾插入10,当fb时,不进行插入操作;

此时s的首尾字符一定不相等,则s去除首尾字符,接着对新的s进行相同的考虑即可。(进行插入操作时要记录该插入点前面的字符数量,特别注意s开头删除过的字符)

当插入次数大于300时,答案为1,否则输出插入操作数和具体操作。

时间复杂度:O(n)

 1 void solve()
 2 {
 3     int n;
 4     cin >> n;
 5 
 6     string s;
 7     cin >> s;
 8 
 9     deque<char> dq;
10     for (auto i : s) dq.pb(i);
11     
12     int tim = 0, sf = 0;
13     vector<int> ans;
14     while (dq.size() >= 2 && tim <= 300)
15     {
16         auto f = dq.front(), b = dq.back();
17         sf++;
18         if (f != b)
19         {
20             dq.pop_back();
21             dq.pop_front();
22         }
23         else 
24         {
25             tim++;
26             if (f == '0')
27             {
28                 ans.push_back(dq.size() + sf);
29                 dq.pop_front();
30                 dq.push_back('0');
31             }
32             else 
33             {
34                 ans.push_back(0 + sf);
35                 dq.pop_back();
36                 dq.push_front('1');
37             }
38         }
39     }
40 
41     if (tim > 300 || dq.size() == 1) cout << -1 << '\n';
42     else 
43     {
44         cout << ans.size() << '\n';
45         for (auto i : ans) cout << i << " ";
46         cout << '\n';
47     }
48 }

D. Doremy's Connecting Plan

若所有点能加边连通,则最优方法是点2到点n按某种顺序与点1依次相连来实现,换言之,若两不为1且不同的点能先连边,则他们都能与1先后连边。

简要证明:1ij都不能连边即a1+ai<ica1+aj<jc,两式相加即2a1+ai+aj<c(i+j),i与j能连边即ai+ajcij,显然ij>i+j,前后两式相矛盾,证毕。

则可以用贪心的方法使点2到点nica[i]的值升序排序,依次与点1相连即可。

时间复杂度:O(nlogn)

 1 #define int long long
 2 
 3 void solve()
 4 {
 5     int n, c;
 6     cin >> n >> c;
 7 
 8     vector<int> a(n + 1);
 9     for (int i = 1; i <= n; i++) cin >> a[i];
10 
11     vector<int> order(n + 1);
12     iota(order.begin() + 2, order.end(), 2);
13     sort(order.begin() + 2, order.end(), [&](int i, int j){return i * c - a[i] < j * c - a[j];});
14 
15     int now = a[1];
16     for (int i = 2; i <= n; i++)
17     {
18         int j = order[i];
19         if (now + a[j] < j * c)
20         {
21             cout << "NO\n";
22             return;
23         }
24         now += a[j];
25     }
26     cout << "YES\n";
27 }

E1. Doremy's Drying Plan (Easy Version)

首先可以用差分数组和前缀和求出每一天被的覆盖次数d,则d=0的天数一定为答案的一部分,又因为可以撤消其中的两个区间,所以d=1d=2的天数都有可能更新答案,则我们可以枚举两个区间AB来实现。

分两种情况枚举,当AB不相交时,则直接选择使d=1的天数减去最多的两个区间即可;当AB相交时,我们只需要枚举每处使d=2AB即可,显然这样的AB不超过n对。

时间复杂度:O(mlogn)

 1 void solve()
 2 {
 3     int n, m, k;
 4     cin >> n >> m >> k;
 5 
 6     vector<int> d(n + 2);
 7     vector<int> l(m + 1), r(m + 1);
 8     for (int i = 1; i <= m; i++) 
 9     {
10         cin >> l[i] >> r[i];
11         d[l[i]]++, d[r[i] + 1]--;
12     }
13 
14     vector s(3, vector<int>(n + 1));
15     for (int i = 1; i <= n; i++)
16     {
17         d[i] += d[i - 1];
18         for (int j = 1; j <= 2; j++)
19             s[j][i] = s[j][i - 1] + (d[i] == j);
20     }
21 
22     int cnt = count(d.begin() + 1, d.end() - 1, 0), ans = cnt;
23 
24     multiset<int> c1;
25     for (int i = 1; i <= m; i++)
26         c1.insert(s[1][r[i]] - s[1][l[i] - 1]);
27     auto it = --c1.end();
28     ans += (*it) + (*(--it));
29 
30     set<int> c2;
31     for (int i = 1; i <= n; i++)
32     {
33         if (d[i] != 2) continue;
34         c2.insert(i);
35     }
36 
37     vector a(n + 1, vector<int>(0));
38     for (int i = 1; i <= m; i++)
39     {
40         auto it = c2.lower_bound(l[i]);
41         while (it != c2.end() && (*it) <= r[i])
42         {
43             a[(*it)].push_back(i);
44             it++;
45         }
46     }
47 
48     for (int i = 1; i <= n; i++)
49     {
50         if (d[i] != 2) continue;
51         int seg1 = a[i][0], seg2 = a[i][1];
52         int L1 = min(l[seg1], l[seg2]), L2 = max(l[seg1], l[seg2]);
53         int R1 = max(r[seg1], r[seg2]), R2 = min(r[seg1], r[seg2]);
54         int val = s[1][R1] - s[1][L1 - 1] + s[2][R2] - s[2][L2 - 1];
55         ans = max(ans, val + cnt);
56     }
57 
58     cout << ans << '\n';
59 }
posted @   会有续命晴空  阅读(146)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示