好久没写codeforces题解,这次E1赛后才做出来,为了方便点,先不把题目挂出来了
比赛链接:https://codeforces.com/contest/2062
A.String
思路:显然可以发现,选择方法形如10101,这种其实是最佳的,然后可以发现这种变成全0的次数等于其1的个数,故归纳一下,本题答案就是对应字符串1的个数
#include<iostream>#include<queue>#include<map>#include<set>#include<vector>#include<algorithm>#include<deque>#include<cctype>#include<string.h>#include<math.h>#include<time.h>#include<random>#include<functional>#include<stack>#include<string>#define ll long long #define lowbit(x) (x & -x)#define endl "\n"// 交互题记得删除using namespace std;mt19937 rnd(time(0));const ll mod = 998244353;//const ll p=rnd()%mod;ll ksm(ll x, ll y){ll ans = 1;while (y){if (y & 1){ans = ans % mod * (x % mod) % mod;}x = x % mod * (x % mod) % mod;y >>= 1;}return ans % mod % mod;}ll gcd(ll x, ll y){if (y == 0)return x;elsereturn gcd(y, x % y);}void fio(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}struct s{ll l,r;bool operator<(const s&a){}};int main(){fio();ll t;cin>>t;while(t--){string f;cin>>f;ll cnt=0;for(ll i=0;i<f.size();i++){cnt+=(f[i]=='1');}cout<<cnt<<endl;}}
B.Clockwork
思路:考虑最坏情况即可,即从一个点出发,从该点出发前往最远端回来,如果回来之前变为0,则一定无解。如果都满足,显然移动周期内都可以过所有点一遍的
#include<iostream>#include<queue>#include<map>#include<set>#include<vector>#include<algorithm>#include<deque>#include<cctype>#include<string.h>#include<math.h>#include<time.h>#include<random>#include<functional>#include<stack>#include<string>#define ll long long #define lowbit(x) (x & -x)#define endl "\n"// 交互题记得删除using namespace std;mt19937 rnd(time(0));const ll mod = 998244353;//const ll p=rnd()%mod;ll ksm(ll x, ll y){ll ans = 1;while (y){if (y & 1){ans = ans % mod * (x % mod) % mod;}x = x % mod * (x % mod) % mod;y >>= 1;}return ans % mod % mod;}ll gcd(ll x, ll y){if (y == 0)return x;elsereturn gcd(y, x % y);}void fio(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}struct s{ll l,r;bool operator<(const s&a){}};ll a[5450000];int main(){fio();ll t;cin>>t;while(t--){ll n;cin>>n;ll pd=0;for(ll i=1;i<=n;i++){ll x;cin>>x;if((i-1)*2>=x||(n-i)*2>=x)pd=1;}if(pd)cout<<"NO"<<endl;else cout<<"YES"<<endl;}}
C.Cirno and Operations
思路:只有两种操作,其实第二种变成差分数组,反转之前和之后,值只有正负之分,绝对值是一样的,数据范围小,暴力枚举即可,其实每次取个最大abs(\(a_n-a_l\))其实应该就可以了
#include<iostream>#include<queue>#include<map>#include<set>#include<vector>#include<algorithm>#include<deque>#include<cctype>#include<string.h>#include<math.h>#include<time.h>#include<random>#include<functional>#include<stack>#include<string>#define ll long long #define lowbit(x) (x & -x)#define endl "\n"// 交互题记得删除using namespace std;mt19937 rnd(time(0));const ll mod = 998244353;//const ll p=rnd()%mod;ll ksm(ll x, ll y){ll ans = 1;while (y){if (y & 1){ans = ans % mod * (x % mod) % mod;}x = x % mod * (x % mod) % mod;y >>= 1;}return ans % mod % mod;}ll gcd(ll x, ll y){if (y == 0)return x;elsereturn gcd(y, x % y);}void fio(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}struct s{ll l,r;bool operator<(const s&a){}};ll a[5450000];int main(){fio();ll t;cin>>t;while(t--){ll n;cin>>n;ll ans=-1e18;ll sum=0;for(ll i=1;i<=n;i++){cin>>a[i];sum+=a[i];}ans=sum;ll l=1,r=n;while(1){sum=0;if(l==r)break;if(a[r]-a[l]>=0){for(ll i=r;i>=l+1;i--){a[i]=a[i]-a[i-1];}l++;}else {for(ll i=l;i<=(l+r)>>1;i++){swap(a[i],a[r-i+l]); }}for(ll i=l;i<=r;i++){sum+=a[i];}ans=max(ans,sum);}cout<<ans<<endl;}}
D.Balanced Tree
思路:本题从树的角度去考虑,如果儿子中的最大值小于等于父亲的值,其实没有必要修改父亲的,但是得传递修改值;如果父亲的值小于儿子的值,其修改值将是所有大于父亲的儿子的值-父亲的值之差的和。所以我们可以发现一个节点的值不能太大也不能太小,所以我们尽量往儿子中的最大值去靠即可(越大,答案越不优;越小,答案只会大于等于最优答案),然后分情况改变下修改值即可。
#include<iostream>#include<queue>#include<map>#include<set>#include<vector>#include<algorithm>#include<deque>#include<cctype>#include<string.h>#include<math.h>#include<time.h>#include<random>#include<functional>#include<stack>#include<string>#define ll long long #define lowbit(x) (x & -x)#define endl "\n"// 交互题记得删除using namespace std;mt19937 rnd(time(0));const ll mod = 998244353;//const ll p=rnd()%mod;ll ksm(ll x, ll y){ll ans = 1;while (y){if (y & 1){ans = ans % mod * (x % mod) % mod;}x = x % mod * (x % mod) % mod;y >>= 1;}return ans % mod % mod;}ll gcd(ll x, ll y){if (y == 0)return x;elsereturn gcd(y, x % y);}void fio(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}struct s{ll l,r;bool operator<(const s&a){}};ll a[5450000];vector<ll>g[250000];ll ans=0;map<ll,pair<ll,ll>>z;ll dfs(ll x,ll f){ll xg=0;vector<pair<ll,ll>>k;ll l=z[x].first;ll r=z[x].second;ll u=0;ll z=0;for(auto j:g[x]){if(j==f)continue;xg+=dfs(j,x);u=max(u,a[j]);if(a[j]>=r)z+=a[j]-r;}if(u>=l&&u<=r){ a[x]=u;return xg;}else if(u<=l){a[x]=l;return xg;}else {a[x]=r;return xg+z;}};int main(){fio();ll t;cin>>t;while(t--){z.clear();ans=0;ll n;cin>>n;for(ll i=1;i<=n;i++){g[i].clear();ll l,r;cin>>l>>r;z[i]={l,r};}for(ll i=1;i<n;i++){ll l,r;cin>>l>>r;g[l].push_back(r);g[r].push_back(l);}cout<<dfs(1,0)+a[1]<<endl;}}
E1.The Game (Easy Version)
思路:没往LCA去想,但是这道题LCA好做,可能答案也是LCA?满足LCA要求后,我们先进行排序,优先值,其次是深度,这个很重要。最大值的所有点不考虑,如果倒序遍历过程中,该值和上一个值不相同,我们就去遍历上一个所有点,如果该点和上一个值点的所有点LCA都是该点则继续,否则解就是该点,break;如果相同,由于进行深度排序了,此时该点的深度比他小,如果该点和上一个点的LCA,只要不是该点,则该点即是答案,break,否则重复上述步骤即可,显然不会TLE
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{ll ans = 1;while (y){if (y & 1){ans = ans % mod * (x % mod) % mod;}x = x % mod * (x % mod) % mod;y >>= 1;}return ans % mod % mod;
}
ll gcd(ll x, ll y)
{if (y == 0)return x;elsereturn gcd(y, x % y);
}
void fio()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
}
ll dep[450000];
struct s
{ll l, r;bool operator<(const s& a){if (r != a.r)return r < a.r;else return dep[l] < dep[a.l];}
}p[405000];
ll a[450000];
vector<ll>g[450000];
vector<ll>k[450000];
ll fa[450000][36];
ll lca(ll x, ll y)
{if (dep[x] < dep[y])swap(x, y);ll dis = dep[x] - dep[y];for (ll i = 30; i >= 0; i--){if ((1ll << i) <= dis){dis -= 1ll << i;x = fa[x][i];}}if (x == y)return x;for (ll i = 30; i >= 0; i--){if (fa[x][i] != fa[y][i])x = fa[x][i], y = fa[y][i];}return fa[x][0];
}
void dfs(ll x, ll f)
{dep[x] = dep[f] + 1;fa[x][0] = f;for (ll i = 1; i <= 31; i++){fa[x][i] = fa[fa[x][i - 1]][i - 1];}for (auto j : g[x]){if (j == f)continue;dfs(j, x);}
}
int main()
{fio();ll t;cin >> t;while (t--){ll n;cin >> n;for (ll i = 1; i <= n; i++){cin >> a[i];p[i].l = i;k[i].clear();p[i].r = a[i];g[i].clear();}for (ll i = 1; i <= n; i++){k[a[i]].push_back(i);}for (ll i = 1; i < n; i++){ll l, r;cin >> l >> r;g[l].push_back(r);g[r].push_back(l);}dfs(1, 0);sort(p + 1, p + 1 + n);ll ans = 0;ll flag = p[n].r;//for(ll i=1;i<=n;i++)cout<<p[i].l<<endl;for (ll i = n - 1; i >= 1; i--){//cout<<p[i].l<<endl;if (p[i].r == p[n].r)continue;if (flag != p[i].r){for (auto j : k[flag]){//if (flag == 3)cout << j << endl;ll u = lca(p[i].l, j);if (u == p[i].l)continue;else ans = p[i].l;}}else if (flag == p[i].r){if (lca(p[i + 1].l, p[i].l) == p[i].l)continue;else ans = p[i].l;}if (ans)break;flag = p[i].r;}cout << ans << endl;}
}