码迷,mamicode.com
首页 > 其他好文 > 详细

2017-10-2 清北刷题冲刺班a.m

时间:2017-10-02 17:49:24      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:push   define   gif   stream   eve   研究   queue   符号   增加   

一道图论神题

(god)

Time Limit:1000ms   Memory Limit:128MB

 

题目描述

LYK有一张无向图G={V,E},这张无向图有n个点m条边组成。并且这是一张带权图,只有点权。

LYK想把这个图删干净,它的方法是这样的。每次选择一个点,将它删掉,但删这个点是需要代价的。假设与这个点相连的还没被删掉的点是u1,u2,…,uk。LYK将会增加a[u1],a[u2],…,a[uk]的疲劳值。

它想将所有点都删掉,并且删完后自己的疲劳值之和最小。你能帮帮它吗?

 

输入格式(god.in)

    第一行两个数n,m表示一张n个点m条边的图。

    第二行n个数ai表示点权。

    接下来m行每行三个数u,v,表示有一条连接u,v的边。数据保证任意两个点之间最多一条边相连,并且不存在自环。

 

输出格式(god.out)

你需要输出这个最小疲劳值是多少。

 

输入样例

4 3

10 20 30 40

1 4

1 2

2 3

 

输出样例

40

 

样例解释

一个合理的方法是先删4号点,此时有10点疲劳值。接下来删3号点,获得20点疲劳值,再删2号点,获得10点疲劳值,最后删1号点,没有疲劳值。总计40点疲劳值。

 

对于30%的数据n<=10。

对于60%的数据n,m<=1000。

对于100%的数据1<=n,m,ai<=100000

技术分享
/*
    贪心
    每次选择权值最大的点删除即可 
*/
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
#define maxn 100010
int n,m,head[maxn],w[maxn];
struct node{
    int to,pre,v;
}e[maxn*2];
struct Node{
    int id,val;
    bool operator < (const Node b)const{
        return val<b.val;
    }
};
priority_queue<Node>q;
int qread(){
    int i=0;
    char ch=getchar();
    while(ch<0||ch>9)ch=getchar();
    while(ch<=9&&ch>=0){i=i*10+ch-0;ch=getchar();}
    return i;
}
void Insert(int from,int to,int v,int num){
    e[num].to=to;
    e[num].pre=head[from];
    e[num].v=v;
    head[from]=num;
}
int main(){
    //freopen("Cola.txt","r",stdin);
    freopen("god.in","r",stdin);freopen("god.out","w",stdout);
    n=qread();m=qread();
    Node now;
    for(int i=1;i<=n;i++){
        w[i]=qread();
        now.id=i;now.val=w[i];
        q.push(now);
    }
    int x,y;
    for(int i=1;i<=m;i++){
        x=qread();y=qread();
        Insert(x,y,w[y],i);Insert(y,x,w[x],i+m);
    }
    long long ans=0;
    while(!q.empty()){
        now=q.top();q.pop();
        int cur=now.id;
        for(int i=head[cur];i;i=e[i].pre){
            ans+=e[i].v;
            if(i<=m)e[i].v=0,e[i+m].v=0;
            if(i>m)e[i].v=0,e[i-m].v=0;
        }
    }
    cout<<ans;
    fclose(stdin);fclose(stdout);
    return 0;
}
100分 贪心

 

位运算2

(bit)

Time Limit:1000ms   Memory Limit:128MB

 

题目描述

LYK拥有一个十进制的数N。它赋予了N一个新的意义:不考虑N的符号,将N每一位都拆开来后再加起来就是N所拥有的价值。例如数字123拥有6的价值,数字999拥有27的价值,数字-233拥有8的价值。

假设数字N的价值是K,LYK想找到一个价值是K+1的数字,当然这个答案实在太多了,LYK想使得这个价值为K+1的数字尽可能大,并且需要保证这个数字小于N。

 

输入格式(bit.in)

    一个整数N。

 

输出格式(bit.out)

一个数表示答案。你需要输出一个整数,且这个数不包含前导0。

 

输入样例1

199

 

输出样例1

-299

 

输入样例2

1520

 

输出样例2

1512

 

对于20%的数据|N|<=10

对于40%的数据|N|<=100

对于60%的数据|N|<=10^9

对于80%的数据|N|<=10^1000

对于100%的数据|N|<=10^100000。

 

逆序对

(pair)

Time Limit:1000ms   Memory Limit:128MB

 

题目描述

LYK最近在研究逆序对。

这个问题是这样的。

一开始LYK有一个2^n长度的数组ai。

LYK有Q次操作,每次操作都有一个参数k。表示每连续2^k长度作为一个小组。假设n=4,k=2,则a[1],a[2],a[3],a[4]为一个小组,a[5],a[6],a[7],a[8]为一个小组,a[9],a[10],a[11],a[12]为一个小组,a[13],a[14],a[15],a[16]也为一个小组。

然后LYK对于每个小组都翻转,也就是说原数组会变成a[4],a[3],a[2],a[1],a[8],a[7],a[6],a[5],a[12],a[11],a[10],a[9],a[16],a[15],a[14],a[13]。之后它想求出这2^n个数的逆序对是多少。

因此你需要输出对于每次操作,操作完后这2^n个数的逆序对有多少对。

两个数ai,aj被称为逆序对当且仅当i<j且ai>aj。

 

输入格式(pair.in)

    第一行一个数n。

接下来一行2^n个数ai表示一开始的数组。

接下来一行一个数Q,表示操作的次数。

接下来一行Q个数,表示每次操作的参数k。

 

输出格式(pair.out)

Q行,表示每次操作后的答案。

 

输入样例

2

2 1 4 3

4

1 2 0 2

 

输出样例

0

6

6

0

 

样例解释

第一次操作,{2,1,4,3}->{1,2,3,4}

第二次操作,{1,2,3,4}->{4,3,2,1}

第三次操作,{4,3,2,1}->{4,3,2,1}       

第四次操作,{4,3,2,1}->{1,2,3,4}

 

对于30%的数据n<=10,Q<=10。

对于50%的数据n<=10,Q<=1000。

对于80%的数据n<=10,Q<=200000。

对于100%的数据n<=17,Q<=200000,1<=ai<=2^n。

 

2017-10-2 清北刷题冲刺班a.m

标签:push   define   gif   stream   eve   研究   queue   符号   增加   

原文地址:http://www.cnblogs.com/thmyl/p/7620388.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!