Codeforces Round #760 (div. 3)
A
解个三元一次方程
rep(i,1,7) cin>>a[i];
sort(a+1,a+8);
cout<<a[1]<<' '<<a[2]<<' '<<a[7]-a[1]-a[2]<<'\n';
B
尾首相同加后t[1],否则加上整个t,不足补a
string s,t,res,d;
cin>>n>>s;
res+=s;
rep(i,1,n-3)
{
cin>>t;
if(t[0]==s[1])
res +=t[1];
else res+= t;
s = t;
}
if(res.size()<n)res+='a';
cout<<res<<endl;
C
对奇数列和偶书列取最小公因数,分别尝试是否能行,不行取0;
cin>>n; int a1=0,b1=0;
rep(i,1,n){
cin>>c[i];
if(i&1) a[a1++] = c[i];
else b[b1++] = c[i];
}
ll ma = maxgysarray(a,a1);
ll mb = maxgysarray(b,b1);
//cout<<ma<<' '<<mb<<endl;
int fa = 0,fb = 0;
rep(i,1,n){
if(i&1){
if(c[i]%mb==0) fa = 1;
}
else if(c[i]%ma==0) fb = 1;
}
//cout<<fg<<fb<<endl;
if(!fa) cout<<mb<<endl;
else if(!fb) cout<<ma<<endl;
else cout<<0<<endl;
D
排序后取最后2*k个,令i=n-k,j = n;从后往前res += i/j即可
cin>>n>>k;
rep(i,1,n) cin>>a[i];
sort(a+1,a+n+1);
int i = n-k,j = n;
int res = 0;
while(k--)
{
res+=a[i--]/a[j--];
}
for(;k<=i;k++) res+=a[k];
cout<<res<<endl;
E
公式推导(高斯是不可能的):bi - bi-1 = \(\Sigma\)ai - n*ai
\(\Sigma\)ai (n+1)n/2 = \(\Sigma\)bi
cin>>n; ll sum = 0;
rep(i,1,n) cin>>a[i],sum += a[i];
bool ok = 1;
if(sum%((n+1)*n/2)) ok = 0;
sum/=((n+1)*n/2);
rep(i,1,n)
{
int j = i-1;
if(!j) j = n;
ll ca = sum - a[i]+a[j];
if(ca%n) ok = 0;
b[i] = ca/n;
if(b[i]<=0) ok = 0;
}
if(ok)
{
cout<<"Yes\n";
rep(i,1,n) cout<<b[i]<<' ';
cout<<endl;
}
else cout<<"No\n";
F
新加入的可能结果二进制必然首尾是1,逆推dfs一下,有环剪下枝
ll reverse(ll x)
{
int cnt = 0;
for (; x; x /= 2)
a[++cnt] = x & 1;
ll y = 0;
for(int i = 1;i<=cnt; i++)
y = y*2 +a[i];
return y;
}
bool dfs(ll x)
{
if(!x) return 0;
if(s.find(x)!=s.end()) return 0;
if(x==x1||x== x2) return 1;
s.insert(x);
if(x&1)
{
if(reverse(x)!=x &&dfs(reverse(x)))
return 1;
int cnt = 0;
for (; x; x /= 2)
a[++cnt] = x & 1;
if(cnt>1 && a[1] && a[2])
{
ll z = 0;
rep(i,2,cnt) z = z*2 + a[i];
if(dfs(z)) return 1;
}
}
return 0;
}
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>x>>y;
if(x==y)
{
puts("Yes"); return 0;
}
x1 = reverse(x*2+1);
x2 = reverse(x*2);
if(dfs(y)) puts("Yes");
else puts("No");
return 0;
}
E(搬运)
题意
Monocarp初始拥有一堆物品,a数组表示它的价值,ai表示物品i的价值。有另外有一堆不属于他的物品,一个数组b表示,表示第i个物品价值为bi。
对于一个固定的k,Monocarp每次可以拿自己拥有的物品去交换,价值为x的物品,可以交换到价值不高于x + k的物品。
现在给定q组询问,每次一个k,问Monocarp能得到的物品价值最多为多少。
题解:
对于一个固定的k,我们把两堆物品合并,然后将价值相差小于等于k的分在同一组。如果这组有x个物品本来属于a,则最优显然是交换到本组价值最高的x个物品。
所以,我们可以让k从小到大排序,从小到大合并差值小于k的组(用并查集),维护组中a物品数,以及组中前x个的和(这个可以通过前缀和得到)。
每次两个组g1, g2合并,g2中物品价值大于g1,则价值改变就是g1中原先取前x个,现在要在g2中取最优的几个(在原先g2中的取完后的前x个)。
我们也可以采用在线做法,让组间按照差值(就是排序后相邻物品价值差)从小到大合并,记录每次合并后的最大价值。查询的时候,二分到到最后一个大于等于k的位置,获取合并后的价值
#include <bits/stdc++.h>
using namespace std;
#define forn(i, n) for(int i = 0; i < int(n); i++)
const int N = 400 * 1000 + 13;
int n, m, k;
int a[N], b[N];
int q[N];
int p[N];
multiset<int> wst[N], bst[N];
long long sum;
int getp(int a){
return a == p[a] ? a : p[a] = getp(p[a]);
}
void unite(int a, int b){
a = getp(a), b = getp(b);
if (wst[a].size() + bst[a].size() < wst[b].size() + bst[b].size()) swap(a, b);
for (auto it : wst[b])
wst[a].insert(it);
for (auto it : bst[b])
bst[a].insert(it);
wst[b].clear();
bst[b].clear();
while (!bst[a].empty() && !wst[a].empty() && *bst[a].begin() < *wst[a].rbegin()){
sum -= *bst[a].begin();
sum += *wst[a].rbegin();
bst[a].insert(*wst[a].rbegin());
wst[a].insert(*bst[a].begin());
bst[a].erase(bst[a].begin());
wst[a].erase(--wst[a].end());
}
p[b] = a;
}
long long ans[N];
struct event{
int x, t, i;
};
int main() {
scanf("%d%d%d", &n, &m, &k);
forn(i, n)
scanf("%d", &a[i]);
forn(i, m)
scanf("%d", &b[i]);
forn(i, k)
scanf("%d", &q[i]);
vector<pair<int, int>> tot;
forn(i, n) tot.push_back({a[i], 1});
forn(i, m) tot.push_back({b[i], 0});
sort(tot.begin(), tot.end());
sum = accumulate(a, a + n, 0ll);
forn(i, n + m){
p[i] = i;
wst[i].clear();
bst[i].clear();
if (tot[i].second) bst[i].insert(tot[i].first);
else wst[i].insert(tot[i].first);
}
vector<event> ev;
forn(i, n + m - 1) ev.push_back({tot[i + 1].first - tot[i].first, 0, i});
forn(i, k) ev.push_back({q[i], 1, i});
sort(ev.begin(), ev.end(), [](const event &a, const event &b){
if (a.x != b.x) return a.x < b.x;
return a.t < b.t;
});
for (auto it : ev){
if (it.t == 0)
unite(it.i, it.i + 1);
else
ans[it.i] = sum;
}
forn(i, k) printf("%lld\n", ans[i]);
}
本文来自博客园,作者:InsiApple,转载请注明原文链接:https://www.cnblogs.com/InsiApple/p/15692672.html

浙公网安备 33010602011771号