2023江西省赛

Danc1ng / 2024-04-25 / 原文

2023江西省赛

Dashboard - 2023 (ICPC) Jiangxi Provincial Contest -- Official Contest - Codeforces

A 签到
L 签到
I 签到 树
J 二次函数 暴力
K 思维
B ⭐⭐ 取模 思维
C ⭐⭐ 博弈 SG函数
H ⭐⭐⭐ 单调队列优化 多重背包
D<---- ⭐⭐⭐ 栈 dp/卡特兰数 思维
E ⭐⭐⭐⭐ 线段树结构题
F ⭐⭐⭐⭐ dp
G ⭐⭐⭐⭐ dp 树链剖分

A - Drill Wood to Make Fire

void solve()
{
    int s,v;
    cin>>n>>s>>v;
    if(s*v>=n) cout<<1<<endl;
    else cout<<0<<endl;
}

L - Zhang Fei Threading Needles - Thick with Fine

void solve()
{
    cin>>n;
    cout<<n-1<<endl;
}

I - Tree

#include <bits/stdc++.h>
#define bug cout << "***************" << endl
#define look(x) cout << #x << " -> " << x << endl
#define endl '\n'
#define int long long
#define YES cout << "YES" << endl;
#define NO cout << "NO" << endl;

using namespace std;
typedef pair<int, int> PII;

constexpr int N = 1e6 + 10 , INF = 2e9;

int n,q;
int e[N],h[N],ne[N],w[N],idx;
int v[N];

void add(int a,int b,int c)
{
    w[idx]=c;
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void solve()
{
    cin>>n>>q;
    memset(h,-1,sizeof h);
    for(int i=0;i<n-1;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c),add(b,a,c);
    }

    while(q--)
    {
        int op;
        cin>>op;
        if(op==1)
        {
            int x,y,z;
            cin>>x>>y>>z;
            v[x]^=z,v[y]^=z;
        }
        else
        {
            int x;cin>>x;
            int res=0;
            for(int i=h[x];~i;i=ne[i])
            {
                int t=w[i];
                // look(t);
                res^=w[i];
            }
            res^=v[x];
            cout<<res<<endl;
        }
    }
}


signed main()
{
    //freopen("check.in","r",stdin);
    //freopen("check.out","r",stdin);
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);

    solve();

    return 0;
}

J - Function

思路:

注意到bi<=n 所以x=a的答案最多为n

对于x=a的最小值 首先考虑对称轴为x=a的函数 ans=min(bi);
对于其他对称轴来说 想要比ans还小 则(a-ai)^2+bi的值一定要小于等于n
也就是(a-ai)^2+bi<=n 则a-sqrt(n-bi)<=ai<=a+sqrt(n-bi)
当bi=0时 x的范围最大 为2sqrt(n);
所以直接枚举即可

/*
J - Function

 */
#include <bits/stdc++.h>
#define bug cout << "***************" << endl
#define look(x) cout << #x << " -> " << x << endl
#define endl '\n'
#define int long long
#define YES cout << "YES" << endl;
#define NO cout << "NO" << endl;

using namespace std;
typedef pair<int, int> PII;

constexpr int N = 1e6 + 10 , INF = 2e9;

int n;
vector<int> b[N];

void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int x;cin>>x;
        b[i].push_back(x);
    }

    int q;cin>>q;
    while(q--)
    {
        int op;
        cin>>op;
        if(op==0)
        {
            int x,y;
            cin>>x>>y;
            b[x].push_back(y);
        }
        else
        {
            int a;
            cin>>a;

            int l=max(1ll,a-(int)sqrt(n)-1ll),r=min(n,a+(int)sqrt(n)+1ll);
            int ans=1e18;

            for(int i=l;i<=r;i++)
            {
                for(int j=0;j<b[i].size();j++)
                {
                    ans=min(ans,b[i][j]+(a-i)*(a-i));
                }
            }
            cout<<ans<<endl;
        }
    }

}


signed main()
{
    //freopen("check.in","r",stdin);
    //freopen("check.out","r",stdin);
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);

    solve();

    return 0;
}

K - Split

思路:

首先考虑查询操作
由于序列是非递增的所以每一段的差值就是左端-右端 进一步的 把相邻数差分 答案也就是这些差分的和
哪些差分需要去掉能使答案最小
假设有一组数 49 39 28 8 3 1
差分为 10 11 29 5 2
如果k=3 假设分成[49][39,..,8][3,1] 那么答案为11+29+2
可以发现49-39之间的10 和 8-3之间的5 不被计算
也就是说分成k个区间后有k-1个差分的数不会被计算
要使答案最小则去掉k-1个最大的差分数即可

对于修改操作
a[x-1],a[x],a[x+1]----a[x-1],a[x-1]+a[x+1]-a[x],a[x+1]
对于差分的数来说 可以发现没有变化 所以 修改操作不会改变整体差分的数的值

/*
K - Split
 */
#include <bits/stdc++.h>
#define bug cout << "***************" << endl
#define look(x) cout << #x << " -> " << x << endl
#define endl '\n'
#define int long long
#define YES cout << "YES" << endl;
#define NO cout << "NO" << endl;

using namespace std;
typedef pair<int, int> PII;

constexpr int N = 1e6 + 10 , INF = 2e9;

int n;
int a[N],b[N],s[N];

void solve()
{
    cin>>n;
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(i!=1)
            b[++cnt]=a[i-1]-a[i];
    }

    sort(b+1,b+cnt+1);

    // for(int i=1;i<=cnt;i++)
    //     cout<<b[i]<<" \n"[i==n];
    // look(cnt);

    for(int i=1;i<=cnt;i++)
        s[i]=s[i-1]+b[i];

    int q;
    cin>>q;
    while(q--)
    {
        int op,x;
        cin>>op>>x;
        if(op==1)
        {
            cout<<s[cnt-x+1]<<endl;
        }
    }

}


signed main()
{
    //freopen("check.in","r",stdin);
    //freopen("check.out","r",stdin);
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);

    solve();

    return 0;
}