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;
    }
}
posted @ 2025-05-06 11:02  长皆  阅读(144)  评论(0)    收藏  举报