Codeforces Round 1023 (Div. 2)(A~C,D,F1补)
A.LRC and VIP
思路:如果全一样,当然无解,否则取一个最大的当1,其他分2即可
吐槽;赛时sort了一遍,wa了一发,问题是还没立马发现自己sort了,无语了
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update> f;
//find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
ll gcd(ll x, ll y)
{
if (y == 0)return x;
else return gcd(y, x % y);
}
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct s
{
ll l, r;
friend bool operator<(const s& a, const s& b)
{
return a.l < b.l;
};
};
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为右边开始的逆时针,后面四个为角落
ll zs[2500000];
ll cnt = 0;
void ola(ll x)
{
vector<bool>vis(x + 5);
for (ll i = 2; i <= x; i++)
{
if (!vis[i])zs[++cnt] = i;
for (ll j = 1; i * zs[j] <= x; j++)
{
vis[i * zs[j]] = 1;
if (i % zs[j] == 0)break;
}
}
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
vector<ll>a(n+5);
ll cnt=0;
ll u=0;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
cnt+=(a[i]==a[1]);
u=max(u,a[i]);
}
if(cnt==n)cout<<"No"<<endl;
else
{
cout<<"Yes"<<endl;
// sort(a.begin()+1,a.begin()+1+n);
for(ll i=1;i<=n;i++)
{
if(a[i]==u)cout<<1<<" ";
else cout<<2<<" ";
}
cout<<endl;
}
}
return 0;
}
B.Apples in Boxes
思路:首先如果最大值减最小值如果大于k+1,那么显然是先手必输的。
如果刚好等于看k+1,且有且仅有一个最大值,那么显然可以根据奇偶性得出谁赢谁输,否则还是先手必输
如果小于等于k,那么就看奇偶性了
吐槽:一开始敲了个对的,后面意识到可能某个盒子里的苹果没了,那么就不用理了,然后重新写了一遍,然后看了下样例,原来是我想错了,立马回退交第一版代码。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update> f;
//find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
ll gcd(ll x, ll y)
{
if (y == 0)return x;
else return gcd(y, x % y);
}
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct s
{
ll l, r;
friend bool operator<(const s& a, const s& b)
{
return a.l < b.l;
};
};
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为右边开始的逆时针,后面四个为角落
ll zs[2500000];
ll cnt = 0;
void ola(ll x)
{
vector<bool>vis(x + 5);
for (ll i = 2; i <= x; i++)
{
if (!vis[i])zs[++cnt] = i;
for (ll j = 1; i * zs[j] <= x; j++)
{
vis[i * zs[j]] = 1;
if (i % zs[j] == 0)break;
}
}
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n,k;
cin>>n>>k;
vector<ll>a(n+5);
ll sum=0;
ll l=0,r=1e18;
for(ll i=1;i<=n;i++)cin>>a[i],sum+=a[i],l=max(l,a[i]),r=min(r,a[i]);
ll pd=0;
swap(l,r);
if(r-l>k+1)pd=0;
else if(r-l==k+1)
{
ll gs=0;
for(ll j=1;j<=n;j++)
{
gs+=(a[j]==r);
}
if(gs==1&&(sum&1))pd=1;
}
else if(sum&1)pd=1;
if(pd)cout<<"Tom"<<endl;
else cout<<"Jerry"<<endl;
// if(k==1)
// {
// if(r-l+1)
// if(n==1)
// {
// if(sum&1)pd=1;
// }
// else
// {
// }
// }
// else
// {
// }
}
return 0;
}
C.Maximum Subarray Sum
思路:显然得特判字符串全1的情况,如果此时符合要求就输出yes和数,否则就输出No。
然后先假设字符串0时为-1e18,再跑一遍最大连续子数组,如果此时最大值大于k,那么必定无解,否则必定有解。我们只需要到第一个字符串为0的地方,然后往左和右跑一个连续数组最大值c1,c2,注意往右跑遇到字符串为0的地方得终止,然后赋值为k-c1-c2,其他0的位置赋值-1e18即可
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update> f;
//find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
ll gcd(ll x, ll y)
{
if (y == 0)return x;
else return gcd(y, x % y);
}
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct s
{
ll l, r;
friend bool operator<(const s& a, const s& b)
{
return a.l < b.l;
};
};
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为右边开始的逆时针,后面四个为角落
ll zs[2500000];
ll cnt = 0;
void ola(ll x)
{
vector<bool>vis(x + 5);
for (ll i = 2; i <= x; i++)
{
if (!vis[i])zs[++cnt] = i;
for (ll j = 1; i * zs[j] <= x; j++)
{
vis[i * zs[j]] = 1;
if (i % zs[j] == 0)break;
}
}
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n,k;
cin>>n>>k;
string f;
cin>>f;
f='0'+f;
vector<ll>a(n+5);
for(ll i=1;i<=n;i++)cin>>a[i];
ll sum=0;
for(ll i=1;i<f.size();i++)sum+=(f[i]=='1');
if(sum==n)
{
ll cnt=0;
ll d=0;
for(ll i=1;i<=n;i++)
{
if(cnt+a[i]>=0)cnt+=a[i];
else cnt=0;
d=max(d,cnt);
}
if(d==k)
{
cout<<"Yes"<<endl;
for(ll i=1;i<=n;i++)cout<<a[i]<<" ";
cout<<endl;
}
else cout<<"No"<<endl;
}
else
{
ll d=0;
ll cnt=0;
for(ll i=1;i<=n;i++)
{
if(f[i]=='1')
{
if(cnt+a[i]>=0)cnt+=a[i];
else cnt=0;
}
else cnt=0;
d=max(d,cnt);
}
if(d>k)cout<<"No"<<endl;
else
{
ll ok=0;
for(ll i=1;i<=n;i++)
{
if(f[i]=='0')
{
if(ok==0)
{
ll c1=0;
ll d1=0;
for(ll j=i-1;j>=1;j--)
{
c1+=a[j];
d1=max(d1,c1);
}
ll c2=0,d2=0;
for(ll j=i+1;j<=n;j++)
{
if(f[j]=='0')break;
c2+=a[j];
d2=max(d2,c2);
}
a[i]=k-d1-d2;
ok=1;
}
else a[i]=-1e18;
}
}
cout<<"Yes"<<endl;
for(ll i=1;i<=n;i++)cout<<a[i]<<" ";
cout<<endl;
}
}
}
return 0;
}
D.Apple Tree Traversing
思路:维护一个树直径,那么我们考虑对于每个点维护能到达的最远且最大的端,要求两个端点不能在同一个儿子的子树内(可以两个为本身,或者一个为本身,一个为儿子子树内的点)。以深度求出路径长,最大点,次大点,现在这个点,四个值做个优先队列。
每次通过儿子向父亲跳打上标记,这样路径就能标记了。随后考虑更新问题,可以很容易发现,其实我在现在这个点往上跳,只要他的父亲没被标记且父亲的两个最远端有一个是从当前点来的,才需要更新,于是遍历一遍父亲连的点(除了父亲的父亲),进行更新替换即可。记得用一个pair数组去记录当前点连了哪两个点和vis数组,用于队列踢出不合法的答案。
吐槽:写出来了,可惜赛时wa了4发,没改出错误点。一开始跑树的时候两个最远端维护没判断好(最好用sort走一遍,用if,else去弄容易出错),还有就是更新的时候,没有判断遍历更新不能走父亲,甚是可惜。下午发现,我的代码跑的巨快,234ms。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update> f;
//find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
ll gcd(ll x, ll y)
{
if (y == 0)return x;
else return gcd(y, x % y);
}
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct s
{
ll w, u1, u2, z;
friend bool operator<(const s& a, const s& b)
{
if (a.w != b.w)return a.w < b.w;
else if (a.u1 != b.u1)return a.u1 < b.u1;
else return a.u2 < b.u2;
};
};
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为右边开始的逆时针,后面四个为角落
ll zs[2500000];
ll cnt = 0;
void ola(ll x)
{
vector<bool>vis(x + 5);
for (ll i = 2; i <= x; i++)
{
if (!vis[i])zs[++cnt] = i;
for (ll j = 1; i * zs[j] <= x; j++)
{
vis[i * zs[j]] = 1;
if (i % zs[j] == 0)break;
}
}
}
pair<ll, ll>aa[200000];
int main()
{
fio();
ll t;
cin >> t;
while (t--)
{
ll n;
cin >> n;
vector<ll>g[n+ 5];
for (ll i = 1; i < n; i++)
{
ll l, r;
cin >> l >> r;
g[l].push_back(r);
g[r].push_back(l);
}
vector<bool>vis(n + 5, 0);
vector<ll>dep(n + 5), fa(n + 4);
priority_queue<s>k;
dep[0] = 0;
function<ll(ll, ll)>dfs = [&](ll x, ll f)
{
dep[x] = dep[f] + 1;
fa[x] = f;
ll x1 = x, x2 = x;
for (auto j : g[x])
{
if (j == f)continue;
ll u = dfs(j, x);
if (dep[x1] < dep[u])swap(x1, x2), x1 = u;
else if (dep[x2] < dep[u])x2 = u;
else if (dep[x1] == dep[x2] && dep[x1] == dep[u])
{
if (x1 < x2)x1=max(x1,u);
else x2 = max(x2,u);
}
else if(dep[x2]==dep[u])x2=max(x2,u);
if(dep[x1]==dep[x2]&&x1<x2)swap(x1,x2);
}
aa[x] = { max(x1,x2),min(x1,x2) };
k.push({ dep[x1] + dep[x2] - 2*dep[x]+1,max(x1,x2),min(x1,x2),x });
if (dep[x1] == dep[x2])return max(x1, x2);
else return x1;
};
dfs(1, 0);
vector<pair<ll, pair<ll, ll>>>ans;
function<ll(ll, ll)>q = [&](ll x, ll y)
{
if (dep[x] == dep[y])return max(x, y);
else if (dep[x] < dep[y])return y;
else return x;
};
function<void(ll, ll)>xg = [&](ll x, ll z)
{
if (vis[x] || x == 0)return;
else
{
if (aa[x].second == z)
{
swap(aa[x].first, aa[x].second);
}
if (aa[x].first == z)
{
aa[x].first = x;
for (auto j : g[x])
{
if (vis[j]||j==fa[x])continue;
else if (aa[j].first == aa[x].second || aa[j].second == aa[x].second)continue;
else
{
aa[x].first = q(aa[x].first, aa[j].first);
aa[x].first = q(aa[x].first, aa[j].second);
}
}
if(aa[x].first<aa[x].second)swap(aa[x].first,aa[x].second);
k.push({ dep[aa[x].first] + dep[aa[x].second] - 2*dep[x]+1,aa[x].first,aa[x].second,x });
xg(fa[x], z);
}
else return;
}
};
while (!k.empty())
{
ll w = k.top().w;
ll l = k.top().u1;
ll r = k.top().u2;
ll id = k.top().z;
k.pop();
if (vis[id])continue;
else if (aa[id].first == l && aa[id].second == r)
{
ans.push_back({ w,{max(l,r),min(l,r)} });
ll u = l;
while (u != id)
{
vis[u] = 1;
u = fa[u];
}
u = r;
while (u != id)
{
vis[u] = 1;
u = fa[u];
}
vis[id] = 1;
xg(fa[id], q(aa[id].first, aa[id].second));
}
}
for (auto j : ans)
{
cout << j.first << " " << j.second.first << " " << j.second.second << " ";
}
cout << endl;
}
return 0;
}
F1.Cycling (Easy Version)
思路:这道题贪心不对,给个例子吧。
1
5
1 2 2 2 4
。
显然我们可以发现,对于1 3 3 3这种其实刚好换了就不亏也不赚,主要是遇到极大值时,我们不好去判断他应该去换哪个比较优秀,毕竟1 2 2 2这种换了就亏了,于是这道题得dp。
显然我们每次可以额外用1代价去带着这个数往前跑,于是我们只要去倒序枚举每个转移点,后面的点必须是第一个最小的,随后再去暴力枚举转移可能就可以得出答案。最小值位置往前不需要dp,往后可以考虑最小值移动到此位置并且再往前带这个值到当前点。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update> f;
//find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
ll gcd(ll x, ll y)
{
if (y == 0)return x;
else return gcd(y, x % y);
}
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct s
{
ll w, u1, u2, z;
friend bool operator<(const s& a, const s& b)
{
if (a.w != b.w)return a.w < b.w;
else if (a.u1 != b.u1)return a.u1 < b.u1;
else return a.u2 < b.u2;
};
};
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为右边开始的逆时针,后面四个为角落
ll zs[2500000];
ll cnt = 0;
void ola(ll x)
{
vector<bool>vis(x + 5);
for (ll i = 2; i <= x; i++)
{
if (!vis[i])zs[++cnt] = i;
for (ll j = 1; i * zs[j] <= x; j++)
{
vis[i * zs[j]] = 1;
if (i % zs[j] == 0)break;
}
}
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
vector<ll>a(n+5);
for(ll i=1;i<=n;i++)cin>>a[i];
vector<ll>dp(n+4,1e18);
dp[n+1]=0;
for(ll i=n;i>=1;i--)
{
ll w=i;
for(ll j=i+1;j<=n;j++)
{
if(a[j]<a[w])w=j;//换前面必定不亏
}
for(ll j=w;j<=n;j++)
{
dp[i]=min(dp[i],(j-w)+(j-i)*(a[w]+1)+a[w]+dp[j+1]);//w移动到j,花费j-w,由于w位置要取出一次再加a[w],随后携带到i需要(j-i)*(a[w]+1),然后j以前的位置的值得加上
}
}
cout<<dp[1]<<endl;
}
}

浙公网安备 33010602011771号