A. Doremy's Paint 3
题意:给出一个数组\(b\),问能否通过重新排序使得数组满足\(b_1+b_2=b_2+b_3=...=b_{n-1}+b_{n}\)
Solution
首先判断元素个数
如果是1,则满足条件
如果是2,需判断不同元素个数的差是否小于等于1
其余的均不满足条件
void solve()
{
int n;
cin >> n;
set<int> st;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
st.insert(a[i]);
}
if (st.size() == 1)
{
cout << "Yes\n";
}
else if (st.size() > 2)
{
cout << "No\n";
}
else
{
int cnt1 = 0, cnt2 = 0;
for (int i = 1; i <= n; i++)
{
if (a[i] == a[1])
cnt1++;
else
cnt2++;
}
if(abs(cnt1-cnt2)<=1)
{
cout<<"Yes\n";
}else
{
cout<<"No\n";
}
}
}
B. Qingshan Loves Strings
题意:给出两个01串\(s,t\),问能否通过若干次(可以是0次)以下操作,使得\(s\)中相邻的字符都不同
操作:向\(s\)中任意一个位置插入字符串\(t\)
Solution
字符串\(t\)内的相邻元素都不同才可行,再考虑\(s\)的情况
如果\(s\)中有相邻的0,则\(t\)的最左和最右都必须是1
如果\(s\)中有相邻的1,则\(t\)的最左和最右都必须是0
如果既有相邻的0又有相邻的1,则不可行
void solve()
{
int n, m;
cin >> n >> m;
string s, t;
cin >> s >> t;
int flag = 1;
for (int i = 0; i < n - 1; i++)
{
if (s[i] == s[i + 1])
{
flag = 0;
break;
}
}
if (flag)
{
cout << "Yes\n";
return;
}
flag = 1;
for (int i = 0; i < m - 1; i++)
{
if (t[i] == t[i + 1])
{
flag = 0;
break;
}
}
if (!flag)
{
cout << "No\n";
return;
}
int flag0 = 0, flag1 = 0;
for (int i = 0; i < n - 1; i++)
{
if (s[i] == s[i + 1] && s[i] == '0')
{
flag0 = 1;
}
else if (s[i] == s[i + 1] && s[i] == '1')
{
flag1 = 1;
}
}
if (t[0] != t[m - 1])
{
cout << "No\n";
return;
}
if (flag0 && !flag1 && t[0] == '1')
{
cout << "Yes\n";
}
else if (!flag0 && flag1 && t[0] == '0')
{
cout << "Yes\n";
}
else
cout << "No\n";
}
C. Qingshan Loves Strings 2
题意:给出一个01串\(s\),构造一个操作序列,使得最后得到的字符串满足\(s_i=S_{n-i+1}(1\le i \le n)\)
操作:向任意一个位置插入字符串\("01"\)
Solution
首先,原字符串的0和1的个数必须相同,不然无解
对于一个字符串,假设前\(x\)位和后\(x\)位已经满足条件了,那么继续考虑第\((x+1)\)位
假设它们都是1,那么向左边的1的左边进行一次操作,这样会使得字符串变为\(...011...1...\)
假设它们都是0,那么向右边的0的右边进行一次操作,这样会使得字符串变为\(...0...001...\)
如此进行模拟即可
void solve()
{
int n;
cin >> n;
string s;
cin >> s;
if (n & 1)
{
cout << "-1\n";
return;
}
int flag = 1;
int cnt1 = 0, cnt0 = 0;
for (int i = 0; i < n / 2; i++)
{
if (s[i] != s[n - i])
{
flag = 0;
break;
}
}
if (flag)
{
cout << "0\n";
cout << "\n";
return;
}
for (int i = 0; i < n; i++)
{
if (s[i] == '1')
{
cnt1++;
}
else
cnt0++;
}
if (cnt1 != cnt0)
{
cout << "-1\n";
return;
}
for (int i = 501; i <= 500 + n; i++)
{
a[i] = s[i - 501] - '0';
}
int l = 501, r = 500 + n;
int ll = 501, rr = 500 + n;
vector<int> ans;
while (l < r)
{
int len = rr - ll + 1;
if (a[l] != a[r])
{
l++;
r--;
}
else if (a[l] == 1)
{
ans.push_back(l - ll);
a[l - 1] = 1;
ll -= 2;
l--;
r--;
}
else
{
ans.push_back(len - (rr - r));
a[r + 1] = 0;
rr += 2;
r++;
l++;
}
}
cout << ans.size() << "\n";
for (auto it : ans)
{
cout << it << " ";
}
cout << "\n";
}
D. Doremy's Connecting Plan
题意:给出一个\(n\)个点,初始没有边的无向图,每次可以进行以下操作:
如果\(\sum \limits_S a_k >=i \times j \times c\)(S表示点\(i,j\)各自的联通分量的并集),则在\(i,j\)连接一条无向边
问是否能够使得无向图变成连通图
Solution
贪心,考虑\(u,v\)如果可以连接的话,假设\(a_u=\frac{u\times v \times c}{2}\)
那么对于\(1,u\),因为\(v \ge 2\),所以\(a_u \ge u \times c\)
所以如果可以连边,则一定可以把点1与其相连
struct node
{
int x, y;
bool operator<(const node &t) const &
{
if (y * k - x != t.y * k - t.x)
return y * k - x < t.y * k - t.x;
return y < t.y;
}
} e[N];
void solve()
{
cin >> n >> k;
// vector<int> a(n + 1);
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
a[i] = x;
e[i].x = x;
e[i].y = i;
}
sort(e + 2, e + 1 + n);
for (int i = 2; i <= n; i++)
{
if (a[1] + e[i].x < e[i].y * k)
{
cout << "No\n";
return;
}
else
{
a[1] += e[i].x;
}
}
cout << "Yes\n";
}
E1. Doremy's Drying Plan (Easy Version)
题意:初始\([1,n]\)全为0,给出\(m\)个区间,区间范围是\(1 \le l \le r \le n\),第\(i\)个区间对\([l_i,r_i]\)进行+1操作,现在最多可以删去两个区间,问删完后\([1,n]\)有多少个点是0
Solution
我们先假设不删任何区间,最后得到的\([1,n]\)的情况
对于每个区间,它们覆盖的点的大小可能是1,2,...,m
考虑两种情况:
1.删去两个覆盖点的大小为1数量最多的区间
2.枚举所有大小为2的点,我们可以处理出来哪对区间覆盖在了这个点上面,然后分别统计删去了这些区间对后的答案即可
void solve()
{
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
{
a[i] = a0[i] = a1[i] = vis[i] = 0;
}
vector<node> v;
for (int i = 1; i <= m; i++)
{
cin >> l[i] >> r[i];
v.push_back({l[i], 1, i});
v.push_back({r[i] + 1, -1, i});
}
for (int i = 1; i <= m; i++)
{
a[l[i]]++;
a[r[i] + 1]--;
}
for (int i = 1; i <= n; i++)
{
a[i] = a[i - 1] + a[i];
}
for (int i = 1; i <= n; i++)
{
a0[i] = a0[i - 1] + (a[i] == 0);
a1[i] = a1[i - 1] + (a[i] == 1);
}
int cnt0 = a0[n];
int cnt1 = 0;
vector<int> v1;
for (int i = 1; i <= m; i++)
{
v1.push_back(a1[r[i]] - a1[l[i] - 1]);
}
sort(v1.begin(), v1.end());
sort(v.begin(), v.end());
int ans = cnt0 + v1[m - 1] + v1[m - 2];
map<pii, int> mp;
set<int> st;
int pos = 0;
for (int i = 1; i <= n; i++)
{
while (pos < (int)(v.size()) && v[pos].x == i)
{
if (v[pos].y == 1)
{
st.insert(v[pos].idx);
}
else
{
st.erase(v[pos].idx);
}
pos++;
}
if (st.size() == 2)
{
int x = *(st.begin()), y = *(st.rbegin());
if (x > y)
swap(x, y);
mp[{x, y}]++;
// cout<<i<<":"<<x<<" "<<y<<"\n";
}
}
for (auto &it : mp)
{
int xx = it.first.first, yy = it.first.second;
int res1 = a1[r[xx]] - a1[l[xx] - 1];
int res2 = a1[r[yy]] - a1[l[yy] - 1];
int sum = it.second + res1 + res2;
ans = max(ans, sum + cnt0);
}
cout << ans << "\n";
}
标签:...,906,cout,int,cin,字符串,Div,E1,题意
From: https://www.cnblogs.com/HikariFears/p/17797430.html