Codeforces Round #473 (Div. 2)

/*
B:
题意:给出一组字符串和每个字符串的价值,
再给出可以互相替换价值的字符串编号,最后
给一行字符串,问这行字符串的最小价值。
样例一中因为second与loser在同一组中,所以
可以用loser的价值代替second的价值,得到最
小的总价值。

思路:找出每组可以字符串中的最小价值,令
该组的所有字符串的价值等于最小价值。
*/
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
struct node
{
    string s;
    int cost;
}cl[100010];
int a[100010];
map<string,int> s;
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,k,m;
    cin>>n>>k>>m;
    int mi;
    for(int i = 0; i < n; i++)
        cin>>cl[i].s;
    for(int i = 0; i < n; i++)
    {
        cin>>cl[i].cost;
        s[cl[i].s] = cl[i].cost;
    }
    while(k--)
    {
        mi = inf;
        int x,y;
        cin>>x;
        for(int i = 0; i < x; i++)
        {
            cin>>y;
            a[i] = y-1;
            mi = min(cl[a[i]].cost,mi);
        }
        for(int i = 0; i < x; i++)
        {
            cl[a[i]].cost = mi;
            s[cl[a[i]].s] = mi;
        }
    }
    long long sum = 0;
    while(m--)
    {
        string str;
        cin>>str;
        sum += s[str];
    }
    cout<<sum<<endl;
    return 0;
}


/*
C
题意:略。。。(看样例解释)
思路:当n小于等于5时题目给出的解法是正确的;
大于5时,将三个节点放在1下,其余全部放在2下
就可以构造出与题意解法不同的。让每个节点都只
有一个子节点就可以构造出与题目相同的。
*/
#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin>>n;
    if(n <= 5)
    {
        cout<<"-1"<<endl;
        for(int i = 2; i <= n/2+1; i++)
            printf("1 %d\n",i);
        for(int i = n/2+2; i <= n; i++)
            printf("2 %d\n",i);
    }
    else
    {
        for(int i = 2; i <= n/2+1; i++)
            printf("1 %d\n",i);
        for(int i = n/2+2; i <= n; i++)
            printf("2 %d\n",i);
        if(n % 2 == 0)
        {
            for(int i = 2; i <= n/2+1; i++)
                printf("1 %d\n",i);
            for(int i = 2; i < n/2+1; i++)
                printf("%d %d\n",i,i+n/2);
        }
        else
        {
            for(int i = 2; i <= n/2+1; i++)
                printf("1 %d\n",i);
            for(int i = 2; i <= n/2+1; i++)
                printf("%d %d\n",i,i+n/2);
        }
    }
    return 0;
}
/*
E
题意:给出一个图,图的节点的编号为1~n,每个节点
之间都有一条边,边权为两节点的编号的异或和,问这
个图的最小生成树。
思路:对于每个节点编号x,找到1~x-1中与x异或的最小
值,这个值应该是x二进制中的最后一位1开始代表的数,
比如:要找x为二进制数11100,应该在1~11011中找,应
该是11000,最后异或的结果为100,即8。但是题目n的范
围为10^12,直接求每个数再求和会超时。
那么我们可以先打表求出一些数对应的值,然后找规律。
可以看出每隔4个就有一个2,每隔8个就有一个4,每隔16
个就有一个8。。。
*/
#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL lowbit(LL x)
{
    return x & (-x);
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    LL n;
    LL x = 1;
    LL sum = 0;
    cin>>n;
    n--;
    /*for(LL i = 1; i < n; i++)
    {
        sum += lowbit(i);
        cout<<lowbit(i)<<endl;
    }*/
    while(n > 0)
    {
        //cout<<n<<endl;
        //cout<<x<<endl;
        sum += ((n+1)>>1)*x;
        x = x << 1;
        n >>= 1;
    }
    cout<<sum<<endl;
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值