一道图论神题

(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

  1. /*
  2. 贪心
  3. 每次选择权值最大的点删除即可
  4. */
  5. #include<iostream>
  6. #include<cstdio>
  7. #include<queue>
  8. using namespace std;
  9. #define maxn 100010
  10. int n,m,head[maxn],w[maxn];
  11. struct node{
  12. int to,pre,v;
  13. }e[maxn*];
  14. struct Node{
  15. int id,val;
  16. bool operator < (const Node b)const{
  17. return val<b.val;
  18. }
  19. };
  20. priority_queue<Node>q;
  21. int qread(){
  22. int i=;
  23. char ch=getchar();
  24. while(ch<''||ch>'')ch=getchar();
  25. while(ch<=''&&ch>=''){i=i*+ch-'';ch=getchar();}
  26. return i;
  27. }
  28. void Insert(int from,int to,int v,int num){
  29. e[num].to=to;
  30. e[num].pre=head[from];
  31. e[num].v=v;
  32. head[from]=num;
  33. }
  34. int main(){
  35. //freopen("Cola.txt","r",stdin);
  36. freopen("god.in","r",stdin);freopen("god.out","w",stdout);
  37. n=qread();m=qread();
  38. Node now;
  39. for(int i=;i<=n;i++){
  40. w[i]=qread();
  41. now.id=i;now.val=w[i];
  42. q.push(now);
  43. }
  44. int x,y;
  45. for(int i=;i<=m;i++){
  46. x=qread();y=qread();
  47. Insert(x,y,w[y],i);Insert(y,x,w[x],i+m);
  48. }
  49. long long ans=;
  50. while(!q.empty()){
  51. now=q.top();q.pop();
  52. int cur=now.id;
  53. for(int i=head[cur];i;i=e[i].pre){
  54. ans+=e[i].v;
  55. if(i<=m)e[i].v=,e[i+m].v=;
  56. if(i>m)e[i].v=,e[i-m].v=;
  57. }
  58. }
  59. cout<<ans;
  60. fclose(stdin);fclose(stdout);
  61. return ;
  62. }

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。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #define maxn 100010
  5. using namespace std;
  6. int bit[maxn],len,f[maxn],w;
  7. char s[maxn];
  8. bool flag=;
  9. void dfs(int pos,bool limit,int sum){
  10. if(flag)return;
  11. if(sum>w)return;
  12. if(pos==len+){
  13. if(sum==w){
  14. int start=;
  15. while(f[start]==)start++;
  16. for(int i=start;i<=len;i++)printf("%d",f[i]);
  17. flag=;
  18. }
  19. return;
  20. }
  21. if(limit){
  22. for(int i=bit[pos];i>=;i--){
  23. f[pos]=i;
  24. dfs(pos+,limit&&(i==bit[pos]),sum+i);
  25. }
  26. }
  27. else{
  28. for(int i=;i>=;i--){
  29. f[pos]=i;
  30. dfs(pos+,,sum+i);
  31. }
  32. }
  33. }
  34. int main(){
  35. //freopen("Cola.txt","r",stdin);
  36. freopen("bit.in","r",stdin);freopen("bit.out","w",stdout);
  37. scanf("%s",s+);
  38. len=strlen(s+);
  39. if(s[]<=''&&s[]>='')for(int i=;i<=len;i++)bit[i]=s[i]-'';
  40. else {
  41. for(int i=;i<=len;i++)bit[i]=s[i]-'';
  42. bit[]=-;
  43. }
  44. if(bit[]!=-){//n是正数
  45. if(bit[len]<=&&bit[len-]>){
  46. bit[len]+=;
  47. bit[len-]--;
  48. for(int i=;i<=len;i++)printf("%d",bit[i]);
  49. return ;
  50. }
  51. for(int i=;i<=len;i++)w+=bit[i];
  52. w++;
  53. dfs(,,);
  54. if(flag)return ;
  55. int cnt=;
  56. while(w){
  57. if(w>=){
  58. f[++cnt]=;
  59. w-=;
  60. }
  61. else f[++cnt]=w,w=;
  62. }
  63. printf("-");
  64. for(int i=cnt;i>=;i--)printf("%d",f[i]);
  65. }
  66. if(bit[]==-){//n是负数
  67. int now=len;
  68. while(now>&&bit[now]==)now--;
  69. if(bit[now]!=){
  70. bit[now]++;
  71. printf("-");
  72. for(int i=;i<=len;i++)printf("%d",bit[i]);
  73. return ;
  74. }
  75. else{
  76. printf("-1");
  77. for(int i=;i<=len;i++)printf("%d",bit[i]);
  78. return ;
  79. }
  80. }
  81. }

80分 暴力

  1. /*
  2. 全程特判:
  3. 1.最后一位<8,倒数第二位>0,最后一位+2,倒数第二位-1
  4. 2.6368899->6359999
  5. 3.4566544099->4566543992
  6. 从后往前,统计9-a[i]的和,直到>=2。
  7. 再往前,找第一个>0的数,把这个数-1, 再整理下后面的数(一开始全是9...,尽可能大)
  8. */
  9. #include <cmath>
  10. #include <cstdio>
  11. #include <cstdlib>
  12. #include <iostream>
  13. #include <algorithm>
  14. #include <string>
  15. #include <cstring>
  16. using namespace std;
  17. char s[];
  18. int len,sum,i,j,FLAG;
  19. int main()
  20. {
  21. freopen("bit.in","r",stdin);
  22. freopen("bit.out","w",stdout);
  23. scanf("%s",s); FLAG=;
  24. if (s[]!='-')
  25. {
  26. len=strlen(s); sum=;
  27. for (i=len-; i>=; i--)
  28. {
  29. if (s[i]>='' && sum>=)
  30. {
  31. s[i]=char(s[i]-);
  32. sum=;
  33. for (j=i+; j<len; j++)
  34. {
  35. while (sum && s[j]<'')
  36. {
  37. sum--;
  38. s[j]=char(s[j]+);
  39. }
  40. }
  41. int SS=;
  42. for (j=i+; j<len; j++) SS+=s[j]-'';
  43. for (j=i+; j<len; j++)
  44. {
  45. if (SS>=) {s[j]=''; SS-=;} else {s[j]=char(SS+''); SS=;}
  46. }
  47. FLAG=;
  48. break;
  49. }
  50. sum+=''-s[i];
  51. }
  52. if (FLAG)
  53. {
  54. for (i=; i<len; i++) if (s[i]!='') break;
  55. for (j=min(len-,i); j<len; j++) cout<<s[j]; cout<<endl;
  56. return ;
  57. }
  58. cout<<'-';
  59. for (i=len-; i>=; i--)
  60. {
  61. if (s[i]<'')
  62. {
  63. s[i]=char(s[i]+);
  64. FLAG=;
  65. break;
  66. }
  67. }
  68. if (FLAG)
  69. {
  70. for (i=; i<len; i++) if (s[i]!='') break;
  71. for (j=min(len-,i); j<len; j++) cout<<s[j]; cout<<endl;
  72. return ;
  73. }
  74. cout<<;
  75. for (i=; i<len; i++) if (s[i]!='') break;
  76. for (j=min(len-,i); j<len; j++) cout<<s[j]; cout<<endl;
  77. return ;
  78. }
  79.  
  80. FLAG=;
  81. cout<<'-';
  82. len=strlen(s);
  83. for (i=len-; i>=; i--)
  84. {
  85. if (s[i]<'')
  86. {
  87. s[i]=char(s[i]+);
  88. FLAG=;
  89. break;
  90. }
  91. }
  92. if (FLAG)
  93. {
  94. for (i=; i<len; i++) if (s[i]!='') break;
  95. for (j=min(len-,i); j<len; j++) cout<<s[j]; cout<<endl;
  96. return ;
  97. }
  98. cout<<;
  99. for (i=; i<len; i++) if (s[i]!='') break;
  100. for (j=min(len-,i); j<len; j++) cout<<s[j]; cout<<endl;
  101. return ;
  102. }

100分

逆序对

(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。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. #define maxn 131073
  6. int n,a[][maxn],Q,tr[maxn];
  7. long long ans;
  8. int qread(){
  9. int i=;
  10. char ch=getchar();
  11. while(ch<''||ch>'')ch=getchar();
  12. while(ch<=''&&ch>=''){i=i*+ch-'';ch=getchar();}
  13. return i;
  14. }
  15. long long query(int pos){
  16. long long res=;
  17. while(pos){
  18. res+=tr[pos];
  19. pos-=pos&(-pos);
  20. }
  21. return res;
  22. }
  23. void add(int pos,int v){
  24. while(pos<=(<<n)){
  25. tr[pos]++;
  26. pos+=pos&(-pos);
  27. }
  28. }
  29. int main(){
  30. //freopen("Cola.txt","r",stdin);
  31. //freopen("pair.in","r",stdin);freopen("pair.out","w",stdout);
  32. n=qread();
  33. for(int i=;i<=(<<n);i++)a[][i]=qread();
  34. Q=qread();
  35. int x;
  36. for(int i=;i<=Q;i++){
  37. memset(tr,,sizeof(tr));
  38. x=qread();x=(<<x);
  39. for(int j=;j<=(<<n);j+=x)//区间反转
  40. for(int cnt=,k=j,l=j+x-;cnt<=x;cnt++,k++,l--)
  41. a[i&][k]=a[(i-)&][l];
  42. ans=;
  43. for(int j=;j<=(<<n);j++){
  44. ans+=j--query(a[i&][j]);
  45. add(a[i&][j],);
  46. }
  47. cout<<ans<<endl;
  48. }
  49. fclose(stdin);fclose(stdout);
  50. return ;
  51. }

树状数组(考场代码)

  1. /*
  2. 12345678
  3.  
  4. [1,4][5,8]
  5. 56781234
  6.  
  7. [1,2][3,4] [5,6][7,8]
  8. 78563412
  9.  
  10. [1,1][2,2] [3,3][4,4] [5,5][6,6] [7,7][8,8]
  11. 87654321
  12.  
  13. k=4 ->
  14.  
  15. 把一个对k的翻转操作 转变成对k,k-1,k-2,...,1的平移操作
  16. 平移操作对答案有什么影响
  17. 对3进行平移,[1,4][5,8] -> [5,8][1,4] 对于所有8个数为一组,答案=逆序对个数的最大值-当前答案
  18.  
  19. 1,2,2,3 当前逆序对(只考虑i属于[1,2],j属于[3,4]的逆序对)=0 逆序对个数的最大值:2*2-相同对数 = 3
  20.  
  21. 2,3,1,2 答案 = 3-0 = 3
  22.  
  23. 记录一下 所有连续2^k个数的当前逆序对个数,以及逆序对个数的最大值。
  24. 每次操作的时候,转变成平移操作
  25.  
  26. 2^4 16
  27. [x,y] 令 mid=(x+y)/2 对于所有i属于[x,mid] j属于[mid+1,y] 这样逆序对的个数
  28. f[1]=[1,2]+[3,4]+[5,6]+...+[15,16]
  29. f[2]=[1,4]+[5,8]+[9,12]+[13,16]
  30. f[3]=[1,8]+[9,16]
  31. f[4]=[1,16]
  32.  
  33. g来表示最大的逆序对个数 (总共的对数-相同的对数)
  34.  
  35. 对于每次对k进行操作
  36. n^2*2^n
  37. while (Q--)
  38. {
  39. cin>>k;
  40. for (int i=1; i<=k; i++) f[i]=g[i]-f[i];
  41. ans=0;
  42. for (int i=1; i<=n; i++) ans+=f[i];
  43. cout<<ans<<endl;
  44. }
  45. [1,4] [5,8]
  46.  
  47. [5,8] [1,4]
  48.  
  49. */
  50. #include <cmath>
  51. #include <cstdio>
  52. #include <cstdlib>
  53. #include <iostream>
  54. #include <algorithm>
  55. #include <string>
  56. #include <cstring>
  57. #include <map>
  58. #include <vector>
  59. using namespace std;
  60. const int N=(<<)+;
  61. long long st[N][],ST[N][];
  62. int p[N],i,sum,o,a[N],b[N],n,T,PP,now,j,A,RR[N];
  63. void gb(int l,int r)
  64. {
  65. if (l==r) return;
  66. int mid=(l+r)/;
  67. gb(l,mid); gb(mid+,r);
  68. int i=l,j=mid+,o=l;
  69. for (i=l; i<=r; i++) b[i]=a[i];
  70. for (i=r; i>=mid; i--) {RR[i]=i; if (i!=r && b[i+]==b[i]) RR[i]=RR[i+];}
  71. i=l; j=mid+;
  72. while (i<=mid && j<=r)
  73. {
  74. if (b[i]<=b[j]) {a[o++]=b[i];if (b[i]==b[j]) ST[l][p[r-l+]]+=RR[j]-j+; i++;} else
  75. {
  76. a[o++]=b[j]; st[l][p[r-l+]]+=mid-i+;
  77.  
  78. j++;
  79. }
  80. }
  81. if (i<=mid) for (j=i; j<=mid; j++) a[o++]=b[j]; else
  82. if (j<=r) for (i=j; i<=r; i++) a[o++]=b[i];
  83. }
  84. long long t[],TT[];
  85. int main()
  86. {
  87. freopen("pair.in","r",stdin);
  88. freopen("pair.out","w",stdout);
  89. scanf("%d",&n);
  90. sum=(<<n);
  91. for (i=; i<=sum; i++) scanf("%d",&a[i]);
  92. for (i=; i<=; i++) p[<<i]=i;
  93. gb(,sum);
  94. scanf("%d",&T);
  95. for (i=; i<=n; i++)
  96. for (j=; j<=(<<n); j+=(<<i))
  97. {
  98. t[i]+=st[j][i];
  99. TT[i]+=ST[j][i];
  100. }
  101. long long ans=;
  102. while (T--)
  103. {
  104. int Q;
  105. scanf("%d",&Q);
  106. for (i=; i<=Q; i++) t[i]=1ll*(<<i-)*(<<i-)*(<<n-i)-TT[i]-t[i];
  107. for (i=; i<=n; i++) ans+=t[i];
  108. printf("%I64d\n",ans); ans=;
  109. }
  110. return ;
  111. }

100分 区间反转->区间平移

2017-10-2 清北刷题冲刺班a.m的更多相关文章

  1. 2017-10-4 清北刷题冲刺班p.m

    P102zhx a [问题描述]你是能看到第一题的 friends 呢.——hja两种操作:1.加入一个数.2.询问有多少个数是?的倍数.[输入格式]第一行一个整数?,代表操作数量.接下来?行,每行两 ...

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

    P101zhx a [问题描述]你是能看到第一题的 friends 呢.——hjaHja 拥有一套时光穿梭技术,能把字符串以超越光速的速度传播,但是唯一的问题是可能会 GG.在传输的过程中,可能有四种 ...

  3. 2017-10-3 清北刷题冲刺班p.m

    a [问题描述]你是能看到第一题的 friends 呢.——hja给你一个只有小括号和中括号和大括号的括号序列,问该序列是否合法.[输入格式]一行一个括号序列.[输出格式]如果合法,输出 OK,否则输 ...

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

    P99zhx a [问题描述]你是能看到第一题的 friends 呢.——hja怎么快速记单词呢?也许把单词分类再记单词是个不错的选择.何大爷给出了一种分单词的方法,何大爷认为两个单词是同一类的当这两 ...

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

    最大值 (max) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一本书,上面有很多有趣的OI问题.今天LYK看到了这么一道题目: 这里有一个长度为n ...

  6. 2017-10-1 清北刷题冲刺班p.m

    一道图论好题 (graph) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图 ...

  7. 2017-10-7 清北刷题冲刺班p.m

    测试 A 同花顺 文件名 输入文件 输出文件 时间限制 空间限制card.cpp/c/pas card.in card.out 1s 512MB题目描述所谓同花顺,就是指一些扑克牌,它们花色相同,并且 ...

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

    测试 A 消失的数字 文件名 输入文件 输出文件 时间限制 空间限制del.cpp/c/pas del.in del.out 1s 512MB题目描述现在,我的手上有 n 个数字,分别是 a 1 ,a ...

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

    位运算1 (bit) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK拥有一个十进制的数N.它赋予了N一个新的意义:将N每一位都拆开来后再加起来就是N所拥 ...

随机推荐

  1. Shiro身份认证---转

    目录 1. Shro的概念 2. Shiro的简单身份认证实现 3. Shiro与spring对身份认证的实现 前言: Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在 JavaSE 环境 ...

  2. mysql连接超时问题

    前几天使用个脚本不停的查看redis队列中的事件.如果有则把事件取出来,然后进行一些数据库操作. 后来发现,每天的第一次有事件时都会到导致,找不到数据. 后来定位到问题,是mysql在连接长时间无活动 ...

  3. Oracle学习笔记_01_SQL初步

    1.分类 SQL语句分为以下三种类型: DML: Data Manipulation Language        数据操纵语言       DDL: Data Definition Languag ...

  4. QListWidget拖放

    setDragEnabled() 允许拖 setAcceptDrops()允许放 setDragDropMode(QAbstractItemView.DragDrop)设置拖拽模式 setSelect ...

  5. codeforces 627B B. Factory Repairs(线段树)

    B. Factory Repairs time limit per test 4 seconds memory limit per test 256 megabytes input standard ...

  6. bison 编译sql的基本知识

    一.bison是干什么的? bison 是一个语法分析器,把用户输入的内容,根绝在.y文件中事先定义好的规则,构建一课语法分析树.(所谓的规则就是,匹配上对应字符之后,执行相应的动作.) 1.一个简单 ...

  7. Maven 将jar导入本地maven仓库

    目录 环境变量配置maven 执行一下命令即可 诚邀访问我的个人博客:我在马路边 更好的阅读体验点击查看原文:Maven将jar倒入本地maven仓库 原创博客,转载请注明出处 @ 在Java项目开发 ...

  8. [转]HTTP头的Expires与Cache-control

    1.概念 Cache-control用于控制HTTP缓存(在HTTP/1.0中可能部分没实现,仅仅实现了Pragma: no-cache) 数据包中的格式: Cache-Control: cache- ...

  9. 功能强大的Northwoods GoDiagram控件库

    Northwoods GoDiagram控件库用于开发图形应用 Northwoods GoDiagram控件库是付费软件,其官方网址为http://www.nwoods.com/ Northwoods ...

  10. spring IOC 注解@Autowired

    自动装配:按照类型来找 会在xml中找类型一样的, 比如 setMessage(SetName setName)上面有@Autowired,会到xml中找<bean id="setna ...