Codeforces Round 969 (Div. 2)
ab题没啥好说的,b题一开始看题错成线段树了,后面发现维护最大值就过了(我就说b怎么会有线段树)。。。
C:Dora and C++
卡的我死死的,好久没卡c了,数论果然是最短板。。。我有两个推论,但是一个都不会用:
1.翡蜀定理。(但是这题只有正数)(处理两个数的情况)
2.断环为链。(但是我只会n方,即以每个点为起点,把其他点都排在他后面)(处理只有一个数的情况)
正解是这样:
-
确实是翡蜀定理,因为对\(a_i\)减去一个数相当于对其余数加上一个数
-
断环为链只需要把第一个节点放到最后去,并不需要重新维护整个链
把上述两个结论结合我们就可以用\(gcd(a,b)\)一个数去处理所有节点了,结束。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int a[maxn];
signed main() {
int t; cin >> t;
while (t--) {
int n,x,y;
cin>>n>>x>>y;
x=__gcd(x,y);
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+n+1);
if(x==1){
cout<<0<<"\n";
continue;
}
for(int i=1;i<n;i++){
int tmp=(a[n]-a[i])/x;
a[i]+=tmp*x;
}
sort(a+1,a+n+1);
int mx=a[n];int ans=0x3f3f3f3f;
for(int i=1;i<=n;i++){
ans=min(ans,mx-a[i]);
mx=a[i]+x;
}
cout<<ans<<"\n";
}
}
D:
观察出性质即结束。
性质:根节点和叶子节点值相同时叶子节点权为0,否则为1;
所以根节点不是?时可直接求答案。
否则,如果cnt0和cnt1相等,先填根的人一定不优。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
vector<int>E[maxn];
bool vis[maxn];
void dfs(int u,int fa){
if(E[u].size()==1&&E[u][0]==fa){
vis[u]=1;
//cout<<u<<"mk\n";
return;
}
for(int i:E[u]) if(i!=fa)dfs(i,u);
}
signed main() {
ios::sync_with_stdio(false);
// 解除cin和cout的默认绑定,来降低IO的负担使效率提升
cin.tie(NULL); cout.tie(NULL);
int t; cin >> t;
while (t--) {
int n;cin>>n;
for(int i=1;i<=n;i++)if(vis[i])vis[i]=0;
for(int i=1;i<=n;i++)E[i].clear();
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
E[u].push_back(v);
E[v].push_back(u);
}
dfs(1,0);
string s;cin>>s;
int cnt1=0,cnt0=0,cnt=0,cnt2=0;
int ans=0;
for(int i=1;i<n;i++){
if(vis[i+1]){
if(s[i]=='?')cnt++;
else if(s[i]=='1')cnt1++;
else cnt0++;
}
else if(s[i]=='?')cnt2++;
}
//cout<<cnt0<<cnt1<<cnt<<cnt2<<"\n";
if(s[0]=='?'){
int fir=cnt/2,sec=(cnt+1)/2;
if(cnt1==cnt0){
if(cnt2%2)ans=cnt1+sec;
else ans=cnt1+fir;
}
else if(cnt1>cnt0){
ans=cnt1+fir;
}
else{
ans=cnt0+fir;
}
}
else{
int sec=cnt/2,fir=(cnt+1)/2;
int v0=s[0]-'0';
if(v0){
ans=cnt0+fir;
}
else{
ans=cnt1+fir;
}
}
cout<<ans<<"\n";
}
}

浙公网安备 33010602011771号