coderforces #683 div2

A
题意:
1,2,,,,n
对于第j次操作,每一个加j除了选中的一个不加之外
让他们变成相同的

#include <bits/stdc++.h>
#define int long long
using namespace std;
 
void solve()
{
    int n;
    cin>>n;
    cout<<n<<endl;
    for(int i=1;i<=n;i++)
        cout<<i<<" ";
    cout<<endl;
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int _=1;
    cin>>_;
    while(_--)
        solve();
}

B
题意:两两可以乘上-1,问和最大,无非偶数全消去,奇数剩下一个,给abs最小的

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e9+5;
void solve()
{
    int min_=inf;
    int flag=0;
    int sum=0;
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int xx;
            cin>>xx;
            if(xx<0)
                flag++;
            if(abs(xx)<min_)
                min_=abs(xx);
            sum+=abs(xx);
        }
    }
    if(flag%2==0)
        cout<<sum<<endl;
    else
    {
        cout<<sum-2*min_<<endl;
    }
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int _=1;
    cin>>_;
    while(_--)
        solve();
}

C
题意:
给你一个包W装物品,你只能装到[W/2,W]
很显然啊,先把大于W的去掉,就是说如果有一个大于W/2的直接输出,不然直接加直到大于W/2

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e5+5;
int a[maxn];
vector<int>vv;
void solve()
{
    vv.clear();
    int f=1;
    int flag=0;
    int sum=0;
    int n,w;
    cin>>n>>w;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(a[i]>=(w+1)/2&&a[i]<=w)
        {
            flag=i;
        }
        if(a[i]<=w)
        {
            f=0;
            sum+=a[i];
        }
    }
    if(f==1)
    {
        cout<<-1<<endl;
        return ;
    }
    if(flag!=0)
    {
        cout<<1<<endl;
        cout<<flag<<endl;
        return;
    }
    if(sum<(w+1ll)/2)
    {
        cout<<-1<<endl;
        return ;
    }
    sum=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>w)
            continue;
        sum+=a[i];
        vv.push_back(i);
        if(sum>=(w+1ll)/2)
        {
            break;
        }
    }
    cout<<vv.size()<<endl;
    for(int i=0;i<vv.size();i++)
        cout<<vv[i]<<" ";
    cout<<endl;
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int _=1;
    cin>>_;
    while(_--)
        solve();
}

D
题意:
给你两个字符串求a,b 求4*LCS(c,d)-c.size()-d.size()的最大值;
很显然看到LCS dp
维护状态转换的关系

using namespace std;
#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//#pragma comment(linker, "/STACK:102400000,102400000")
#define int long long
const int maxn=5e3+5;
int dp[maxn][maxn];
void solve()
{
    int max_=0;
    int n,m;
    string a,b;
    cin>>n>>m>>a>>b;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(a[i-1]==b[j-1])
                dp[i][j]=dp[i-1][j-1]+2;
            else
                dp[i][j]=max(0ll,max(dp[i-1][j],dp[i][j-1])-1);
            max_=max(max_,dp[i][j]);
        }
    }
    cout<<max_;
}
signed main() {
    int _=1;
    //cin>>_;
    while(_--)
        solve();
    return 0;
}

E
题意:
对于每个点i,找到j≠i且aj xor ai最小,连边(i,j)。
如果连边之后形成一棵树,那么称{ai}为合法的。
给出{ai},求至少删掉多少个点才合法。
n≤2∗105
ai互不相同
题解:
很显然整体异或和最小的那个值被划了两遍,其他的都不能被划两遍,所以除了最小的之外,其他的都只能和有一条异或和比他小的点连接;
哈夫曼0 1
结点分开越早,异或和越大,所有的点都在最下面的叶子,所以分开的时候也就分开了两个不同连通集合,很显然两个连通集是不能相连的,因为你内部的一点肯定比外部的异或和小,除非集合内只有一点,其他点全部删去,遍历删去的每一种情况,取剩下值的最大值,也就是删去的最小值,最后到两个点的时候他们两个都能放进去可以连通主要是

using namespace std;
#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//#pragma comment(linker, "/STACK:102400000,102400000")
#define int long long
const int maxn=2e5+5;
struct node
{
    int size;
    int lc,rc;
    node()
    {
        size=0;
        lc=0;
        rc=0;
    };
};
int cnt;
node no[maxn*30];
void insert(int xx)
{
    int now=0;
    no[now].size+=1;
    for(int i=29;i>=0;i--)
    {
        if(xx>>i&1)
        {
            if(no[now].rc==0)
            {
                cnt++;
                no[now].rc=cnt;
            }
            now=no[now].rc;
        }
        else
        {
            if(no[now].lc==0)
            {
                cnt++;
                no[now].lc=cnt;
            }
            now=no[now].lc;
        }
        no[now].size+=1;
    }
}
int ans;
void dfs(int u,int s)
{
    if(no[u].lc>0&&no[u].rc>0&&no[no[u].lc].size==1&&no[no[u].rc].size==1)
    {
        ans=max(ans,s+2);
        return;
    }
    if(no[u].lc>0)
        dfs(no[u].lc,s+(no[u].rc>0?1:0));
    if(no[u].rc>0)
        dfs(no[u].rc,s+(no[u].lc>0?1:0));
}
void bfs(int u)
{
    cout<<no[u].size<<endl;
    if(no[u].lc>0)
        bfs(no[u].lc);
    if(no[u].rc>0)
        bfs(no[u].rc);
}
void solve()
{
    cnt=0;
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int xx;
        cin>>xx;
        insert(xx);
    }
    //bfs(0);
    ans=2;
    dfs(0,0);
    cout<<n-ans;
}
signed main() {
    int _=1;
    //cin>>_;
    while(_--)
        solve();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值