Codeforces Round 909 (Div. 3)
A.
若n是3的倍数,那么输出第二,因为不管先手如何操作,后手只要跟先手出的相反那么先手就永远不会赢
其他情况,先手都能赢
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
void solve() {
int n;cin>>n;
if((n+1)%3==0||(n-1)%3==0)cout<<"First\n";
else cout<<"Second\n";
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}
B.
暴力枚举
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
#define inf 0x3f3f3f3f3f3f3f3f
void solve() {
int n;cin>>n;
vector<int>a(n+1),pre(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
pre[i]=pre[i-1]+a[i];
}
int ans=0;
int t_mi=inf,t_ma=0;
for(int i=1;i<n;i++){
t_mi=inf,t_ma=0;
if(n%i!=0)continue;
for(int j=1;j+i-1<=n;j+=i){
t_ma=max(t_ma,pre[j+i-1]-pre[j-1]);
t_mi=min(t_mi,pre[j+i-1]-pre[j-1]);
}
ans=max(ans,abs(t_ma-t_mi));
}
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}
C.
dp,其实和最大子序列和一样,只是加上奇偶性不能相邻这个限制即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
#define inf 0x3f3f3f3f
void solve() {
int n;cin>>n;
vector<int>a(n+1);
for(int i=1;i<=n;i++)cin>>a[i];
vector<int>dp(n+1);
dp[1]=a[1];
for(int i=2;i<=n;i++){
if(abs(a[i])%2==0&&abs(a[i-1])%2==0||abs(a[i])%2==1&&abs(a[i-1])%2==1){
// cout<<"i="<<i<<'\n';
dp[i]=a[i];
}
else dp[i]=max({dp[i-1]+a[i],a[i]});
}
int ma=-inf;
for(int i=1;i<=n;i++)ma=max(ma,dp[i]);
cout<<ma<<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}
D.
把式子化简,以2为底的指数形式,发现要让两个相等
需满足2^x/x == 2^y/y
指数是爆炸式增长,比一次函数快得多,发现只有1和2满足相等
其他必须相同才会相等
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
#define inf 0x3f3f3f3f
void solve() {
int n;cin>>n;
vector<int>a(n+1);
for(int i=1;i<=n;i++)cin>>a[i];
map<int,int>mp;
int ans=0;
for(int i=1;i<=n;i++){
if(a[i]==1)ans+=mp[2];
else if(a[i]==2)ans+=mp[1];
ans+=mp[a[i]];
mp[a[i]]++;
}
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}
E.
若最小值在队头,那么它就会一直在队头,因为没有值比它更小
其他值经过操作都会去到自己应该在的位置
所以若第一个最小值后都是非降序的,那么最小操作次数就是第一个最小值前的数的个数
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
#define inf 0x3f3f3f3f
void solve() {
int n;cin>>n;
vector<int>a(n+1);
int mi=inf,id=0;
for(int i=1;i<=n;i++){
cin>>a[i];mi=min(mi,a[i]);
}
int f=0;
for(int i=2;i<=n;i++){
if(a[i]>=a[i-1])continue;
f=1;break;
}
if(f==0){
cout<<0<<'\n';return ;
}
for(int i=1;i<=n;i++){
if(a[i]==mi){
id=i;break;
}
}
f=0;
for(int i=id;i<n;i++){
if(a[i]<=a[i+1])continue;
f=1;break;
}
if(f){
cout<<-1<<'\n';return ;
}
cout<<id-1<<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}
F.
最优的构造方法就是一条单链,因为这样的路径最长
把n号节点作为移动节点,记录链接它的是谁
需要m的路径就把n号节点移动到m号节点上
若n号节点本来就链接的m号节点就是-1
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
#define inf 0x3f3f3f3f
void solve() {
int n,q;cin>>n>>q;
for(int i=1;i<n;i++)cout<<i<<' '<<i+1<<'\n';
int last=n-1;
for(int i=1;i<=q;i++){
int d;cin>>d;
if(last==d){
cout<<"-1 -1 -1\n";
continue;
}
cout<<n<<' '<<last<<' '<<d<<'\n';
last=d;
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}
G.
可以将树上的顶点编号改成对应排列的数组下标
这样使毫无顺序的区间有了顺序
维护每个节点的后代,用set去二分找答案
把询问离线
一个优化:找重儿子,其他的暴力merge合并
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
#define inf 0x3f3f3f3f
int n,q;
void solve() {
cin>>n>>q;
vector<pair<int,int>>e(n-1);
for(auto &[u,v]:e)cin>>u>>v;
vector<int>p(n+1);
for(int i=0;i<n;i++){
int x;cin>>x;p[x]=i;
}
vector<vector<int>>g(n);
for(auto &[u,v]:e){
g[p[u]].emplace_back(p[v]);
g[p[v]].emplace_back(p[u]);
}
vector<vector<tuple<int,int,int>>>w(n);
vector<bool>b(q);
for(int i=0;i<q;i++){
int l,r,x;cin>>l>>r>>x;
w[p[x]].emplace_back(l-1,r-1,i);
}
vector<set<int>>s(n);
function<void(int,int)>dfs=[&](int u,int f){
int h=u;
for(int i:g[u]){
if(i!=f){
dfs(i,u);
if(s[i].size()>s[h].size())h=i;
}
}
if(h!=u)s[u].swap(s[h]);
for(int i:g[u]){
if(i!=f&&i!=h)s[u].merge(s[i]);
}
s[u].emplace(u);
for(auto [l,r,i]:w[u]){
if(auto p=s[u].lower_bound(l);p!=s[u].end()&&*p<=r)b[i]=true;
}
};
dfs(p[1],p[1]);
for(bool i:b)cout<<(i?"YES\n":"NO\n");
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}