1. 程式人生 > >2017-10-2 清北刷題沖刺班a.m

2017-10-2 清北刷題沖刺班a.m

數組 hid stdout 問題 closed 多少 clu 描述 ide

一道圖論神題

(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