T1 水题(water)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK出了道水题。

这个水题是这样的:有两副牌,每副牌都有n张。

对于第一副牌的每张牌长和宽分别是xi和yi。对于第二副牌的每张牌长和宽分别是aj和bj。第一副牌的第i张牌能覆盖第二副牌的第j张牌当且仅当xi>=aj并且yi>=bj。(注意牌不能翻转)当然一张牌只能去覆盖最多一张牌,而不能覆盖好多张。

LYK想让两副牌的各n张一一对应叠起来。它想知道第二副牌最多有几张能被第一副牌所覆盖。

输入格式(water.in)

第一行一个数n。

接下来n行,每行两个数xi,yi。

接下来n行,每行两个数aj,bj。

输出格式(water.out)

输出一个数表示答案。

输入样例

3

2 3

5 7

6 8

4 1

2 5

3 4

输出样例

2

数据范围

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

对于80%的数据n<=1000。

对于100%的数据1<=n<=100000,1<=xi,yi,aj,bj<=10^9。

  1. #include <algorithm>
  2. #include <cstdio>
  3.  
  4. inline void read(int &x)
  5. {
  6. x=; register char ch=getchar();
  7. for(; ch>''||ch<''; ) ch=getchar();
  8. for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
  9. }
  10. const int N();
  11. int n,ans;
  12. struct Node {
  13. int x,y;
  14. bool operator < (const Node&z)const
  15. {
  16. if(x==z.x) return y<z.y;
  17. return x<z.x;
  18. }
  19. }a[N],b[N];
  20. const int M();
  21. int vis[M][M],sumvis;
  22. int link[M][M],mat[M];
  23.  
  24. bool find(int u)
  25. {
  26. for(int v=; v<=n; ++v)
  27. if(link[u][v]&&vis[u][v]!=sumvis)
  28. {
  29. vis[u][v]=sumvis;
  30. if(!mat[v]||find(mat[v]))
  31. {
  32. mat[v]=u;
  33. return ;
  34. }
  35. }
  36. return ;
  37. }
  38.  
  39. inline void violence()
  40. {
  41. for(int i=; i<=n; ++i)
  42. for(int j=; j<=n; ++j)
  43. link[i][j]=(a[i].x>=b[j].x&&a[i].y>=b[j].y);
  44. for(int i=; i<=n; ++i)
  45. {
  46. sumvis++;
  47. if(find(i)) ans++;
  48. }
  49. printf("%d\n",ans);
  50. }
  51.  
  52. int Presist()
  53. {
  54. // freopen("1.txt","r",stdin);
  55. freopen("water.in","r",stdin);
  56. freopen("water.out","w",stdout);
  57. read(n);
  58. for(int i=; i<=n; ++i)
  59. read(a[i].x),read(a[i].y);
  60. for(int i=; i<=n; ++i)
  61. read(b[i].x),read(b[i].y);
  62. if(n<=) violence();
  63. return ;
  64. }
  65.  
  66. int Aptal=Presist();
  67. int main(int argc,char**argv){;}

匈牙利,60分

因为可能存在 xi,yi=1,,,xj==1,yj,的情况,这种情况下,无法确定怎样覆盖更优,

所以可以以xi从小到大排序,在满足xi的情况下,将B组的y放到某数据结构中,再找满足A组的y的最大的y

需要有插入,删除不超过y的最大数的数据结构,数组80,muliset/平衡树/权值线段树

  1. #include <algorithm>
  2. #include <cstdio>
  3. #include <set>
  4.  
  5. inline void read(int &x)
  6. {
  7. x=; register char ch=getchar();
  8. for(; ch>''||ch<''; ) ch=getchar();
  9. for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
  10. }
  11. const int N();
  12.  
  13. std:: multiset<int>set_;
  14.  
  15. struct Card {
  16. int x,y;
  17. bool operator < (const Card&c)const
  18. {
  19. return x<c.x;
  20. }
  21. }a[N],b[N];
  22.  
  23. int Presist()
  24. {
  25. freopen("water.in","r",stdin);
  26. freopen("water.out","w",stdout);
  27. int n,ans=; read(n);
  28. for(int i=; i<=n; ++i)
  29. read(a[i].x),read(a[i].y);
  30. for(int i=; i<=n; ++i)
  31. read(b[i].x),read(b[i].y);
  32. std:: sort(a+,a+n+);
  33. std:: sort(b+,b+n+);
  34. for(int i=,j=; i<=n; ++i)
  35. {
  36. for(; a[i].x>=b[j].x&&j<=n; )
  37. set_.insert(b[j].y),++j;
  38. if(set_.empty()) continue;
  39. std:: multiset<int>:: iterator it=set_.upper_bound(a[i].y);
  40. if(it==set_.begin()) continue;
  41. else ans++,set_.erase(--it);
  42. }
  43. printf("%d\n",ans);
  44. return ;
  45. }
  46.  
  47. int Aptal=Presist();
  48. int main(int argc,char**argv){;}

AC

T2 梦境(dream)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK做了一个梦。

这个梦是这样的,LYK是一个财主,有一个仆人在为LYK打工。

不幸的是,又到了月末,到了给仆人发工资的时间。但这个仆人很奇怪,它可能想要至少x块钱,并且当LYK凑不出恰好x块钱时,它不会找零钱给LYK。

LYK知道这个x一定是1~n之间的正整数。当然抠门的LYK只想付给它的仆人恰好x块钱。但LYK只有若干的金币,每个金币都价值一定数量的钱(注意任意两枚金币所代表的钱一定是不同的,且这个钱的个数一定是正整数)。LYK想带最少的金币,使得对于任意x,都能恰好拼出这么多钱。并且LYK想知道有多少携带金币的方案总数。

具体可以看样例。

输入格式(dream.in)

第一行一个数n,如题意所示。

输出格式(dream.out)

输出两个数,第一个数表示LYK至少携带的金币个数,第二数表示方案总数。

输入样例

6

输出样例

3 2

样例解释

LYK需要至少带3枚金币,有两种方案,分别是{1,2,3},{1,2,4}来恰好得到任意的1~n之间的x。

输入样例2

10

输出样例2

4 8

数据范围

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

对于60%的数据n<=100。

对于100%的数据n<=1000。

  1. #include <algorithm>
  2. #include <cstdio>
  3.  
  4. #define min(a,b) (a<b?a:b)
  5.  
  6. inline void read(int &x)
  7. {
  8. x=; register char ch=getchar();
  9. for(; ch>''||ch<''; ) ch=getchar();
  10. for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
  11. }
  12. const int N();
  13. int n,ans,count;
  14. bool vis[N];
  15. int a[N];
  16.  
  17. void DFS(int num,int cnt,int sum)
  18. {
  19. if(sum>=n) { ans++; return ; }
  20. if(cnt>count) { return ; }
  21. for(int i=num+; i<=min(a[cnt+],sum+); ++i)
  22. {
  23. if(vis[i]) continue; vis[i]=;
  24. DFS(i,cnt+,sum+i); vis[i]=;
  25. }
  26. }
  27.  
  28. int Presist()
  29. {
  30. // freopen("1.txt","r",stdin);
  31. freopen("dream.in","r",stdin);
  32. freopen("dream.out","w",stdout);
  33. read(n);
  34. for(int sum=; sum<n; ++sum)
  35. a[++count]=sum+,sum<<=;
  36. DFS(,,);
  37. printf("%d %d\n",count,ans);
  38. return ;
  39. }
  40.  
  41. int Aptal=Presist();
  42. int main(int argc,char**argv){;}

爆搜30

方案总数:dp,搜索

2^0+2^1+...+2^k = O(n)  k=log(n)

dfs(Max,Sum,S) // Max金币最大值,Sum所有金币的和,S金币的数量

dp[i][j][k] 当前有i个金币,金币和是j,最大的金币k。

if (dp[i][j][k]) 枚举下一枚金币是啥。

  1. #include <cstdio>
  2.  
  3. #define min(a,b) (a<b?a:b)
  4.  
  5. inline void read(int &x)
  6. {
  7. x=; register char ch=getchar();
  8. for(; ch>''||ch<''; ) ch=getchar();
  9. for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
  10. }
  11. int n,cnt,ans,f[][][];
  12.  
  13. int Presist()
  14. {
  15. freopen("dream.in","r",stdin);
  16. freopen("dream.out","w",stdout);
  17.  
  18. read(n);
  19. for(; (<<cnt)<=n; ) cnt++;
  20. f[][][]=;
  21. for(int i=; i<cnt; ++i)
  22. for(int j=; j<=n; ++j)
  23. for(int k=; k<=n; ++k)
  24. {
  25. if(!f[i][j][k]) continue;
  26. for(int p=k+; p<=j+; ++p)
  27. f[i+][min(j+p,n)][p]+=f[i][j][k];
  28. }
  29. for(int i=; i<=n; ++i) ans+=f[cnt][n][i];
  30. printf("%d %d\n",cnt,ans);
  31. return ;
  32. }
  33.  
  34. int Aptal=Presist();
  35. int main(int argc,char**argv){;}

AC

T3 动态规划(dp)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK在学习dp,有一天它看到了一道关于dp的题目。

这个题目是这个样子的:一开始有n个数,一段区间的价值为这段区间相同的数的对数。我们想把这n个数切成恰好k段区间。之后这n个数的价值为这k段区间的价值和。我们想让最终这n个数的价值和尽可能少。

例如6个数1,1,2,2,3,3要切成3段,一个好方法是切成[1],[1,2],[2,3,3],这样只有第三个区间有1的价值。因此这6个数的价值为1。

LYK并不会做,丢给了你。

输入格式(dp.in)

第一行两个数n,k。

接下来一行n个数ai表示这n个数。

输出格式(dp.out)

一个数表示答案。

输入样例

10 2

1 2 1 2 1 2 1 2 1 2

输出样例

8

数据范围

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

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

对于100%的数据1<=n<=100000,1<=k<=min(n,20),1<=ai<=n。

其中有30%的数据满足ai完全相同均匀分布在所有数据中。

dp[i][j] 1~i 切了j刀,的最优解

dp[i][j]=min{dp[k][j-1]+sum(k+1,i)}

这个k是从大到小进行枚举,每次枚举时更新这个sum 20*n^2  60分

  1. #include <cstring>
  2. #include <cstdio>
  3.  
  4. #define min(a,b) (a<b?a:b)
  5. #define LL long long
  6.  
  7. inline void read(int &x)
  8. {
  9. x=; register char ch=getchar();
  10. for(; ch>''||ch<''; ) ch=getchar();
  11. for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
  12. }
  13. const int N();
  14. int a[N],cnt[N],L,R;
  15. int sum[][];
  16. LL f[][];
  17.  
  18. int Presist()
  19. {
  20. freopen("dp.in","r",stdin);
  21. freopen("dp.out","w",stdout);
  22.  
  23. int n,k; read(n),read(k);
  24. for(int i=; i<=n; ++i) read(a[i]);
  25. for(int i=; i<=n; ++i)
  26. {
  27. ++cnt[a[i]];
  28. for(int j=i+; j<=n; ++j)
  29. sum[i][j]=sum[i][j-]+cnt[a[j]],++cnt[a[j]];
  30. memset(cnt,,sizeof(cnt));
  31. }
  32. for(int i=; i<=n; ++i)
  33. for(int j=; j<=k; ++k)
  34. f[i][j]=0x7fffffff;
  35. for(int i=; i<=n; ++i)
  36. {
  37. f[i][]=sum[][i];
  38. for(int j=; j<=min(i,k); ++j)
  39. for(int t=; t<i; ++t)
  40. f[i][j]=min(f[i][j],f[t][j-]+sum[t+][i]);
  41. }
  42. printf("%d\n",f[n][k]);
  43. return ;
  44. }
  45.  
  46. int Aptal=Presist();
  47. int main(int argc,char**argv){;}

固定j,随着i的增大,k不会减少

20*n^2的简单dp -> 在固定j的情况下 随着i的增大,k不降 -> 分治求dp值

  1. #include <cstring>
  2. #include <cstdio>
  3.  
  4. #define LL long long
  5.  
  6. inline void read(int &x)
  7. {
  8. x=; register char ch=getchar();
  9. for(; ch>''||ch<''; ) ch=getchar();
  10. for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
  11. }
  12. const int N();
  13. int a[N],cnt[N],L,R;
  14. LL f[N],g[N],sum;
  15.  
  16. inline void move(int l,int r)
  17. {
  18. for(; L>l; ) sum+=cnt[a[--L]]++;
  19. for(; L<l; ) sum-=--cnt[a[L++]];
  20. for(; R>r; ) sum-=--cnt[a[R--]];
  21. for(; R<r; ) sum+=cnt[a[++R]]++;
  22. }
  23.  
  24. void work(int u,int v,int l,int r)
  25. {
  26. if(l>r) return ;
  27. int mid=l+r>>,pos;
  28. LL minn=0x7fffffff;
  29. for(int i=u; i<mid&&i<=v; ++i)
  30. {
  31. move(i+,mid);
  32. if(sum+f[i]<minn)
  33. minn=sum+f[i],pos=i;
  34. }
  35. g[mid]=minn;
  36. work(u,pos,l,mid-);
  37. work(pos,v,mid+,r);
  38. }
  39.  
  40. int Presist()
  41. {
  42. freopen("dp.in","r",stdin);
  43. freopen("dp.out","w",stdout);
  44.  
  45. int n,k; read(n),read(k);
  46. for(int i=; i<=n; ++i) read(a[i]);
  47. for(int i=; i<=n; ++i) f[i]=0x7fffffff;
  48. for(; k--; )
  49. {
  50. memset(cnt,,sizeof(cnt));
  51. L=,R=,sum=,work(,n-,,n);
  52. for(int i=; i<=n; ++i) f[i]=g[i],g[i]=;
  53. }
  54. printf("%lld\n",f[n]);
  55. return ;
  56. }
  57.  
  58. int Aptal=Presist();
  59. int main(int argc,char**argv){;}

AC

2017-10-28-afternoon-清北模拟赛的更多相关文章

  1. 2017.10.1 国庆清北 D1T1 zhx的字符串题

    题目背景 2017国庆清北D1T1 题目描述 你是能看到第一题的 friends 呢. ——hja 何大爷对字符串十分有研究,于是天天出字符串题虐杀 zhx.何大爷今天为 字符串定义了新的权值计算方法 ...

  2. 2017.10.3北京清北综合强化班DAY3

    括号序列(bracket) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一个括号序列,但这个序列不一定合法. 一个合法的括号序列如下: ()是合法的 ...

  3. 2017.10.4北京清北综合强化班DAY4

    财富(treasure) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有n个小伙伴.每个小伙伴有一个身高hi. 这个游戏是这样的,LYK生活的环境是以 ...

  4. 2017.10.7北京清北综合强化班DAY7

    1.计数 (count.cpp/c/pas) 时间限制:1s 内存限制:256MB [问题描述] 给出m个数a[1],a[2],…,a[m] 求1~n中有多少数不是a[1],a[2],…,a[m]的倍 ...

  5. 2017.10.6北京清北综合强化班DAY6

    题目大意:改变一个数的位置 把一个序列变成不下降序列 题解: 设置一个pre,如果破坏单调性,就把‘删除’这个.否则把pre修改为当前元素的值. 考试时这样得了90分,是因为我的做法只能过这样的数据 ...

  6. 2017.10.5北京清北综合强化班DAY5

    拼不出的数lost.in/.out/.cpp[问题描述]3 个元素的集合{5, 1,2} 的所有子集的和分别是0,1, 2, 3, 5, 6, 7, 8.发现最小的不能由该集合子集拼出的数字是4.现在 ...

  7. 2017.10.1北京清北综合强化班DAY1

    a[问题描述]你是能看到第一题的 friends 呢.——hja何大爷对字符串十分有研究,于是天天出字符串题虐杀 zhx. 何大爷今天为字符串定义了新的权值计算方法.一个字符串 由小写字母组成,字符串 ...

  8. 2017.10.4 国庆清北 D4T2 正方形

    题目描述 在一个10000*10000的二维平面上,有n颗糖果. LYK喜欢吃糖果!并且它给自己立了规定,一定要吃其中的至少C颗糖果! 事与愿违,LYK只被允许圈出一个正方形,它只能吃在正方形里面的糖 ...

  9. 2017.10.6 国庆清北 D6T2 同余方程组

    题目描述 求关于x 的同余方程组 x%a1 = b1 x%a2 = b2 x%a3 = b3 x%a4 = b4 的大于等于0 的最小整数解. 输入输出格式 输入格式: 一行8 个整数,表示a1; b ...

  10. 2017.10.6 国庆清北 D6T1 排序

    题目描述 小Z 有一个数字序列a1; a2; .... ; an,长度为n,小Z 只有一个操作:选 定p(1<p<n),然后把ap 从序列中拿出,然后再插⼊到序列中任意位置. 比如a 序列 ...

随机推荐

  1. ios之UIActionSheet

    UIActionSheet是在IOS弹出的选择按钮项,可以添加多项,并为每项添加点击事件. 为了快速完成这例子,我们打开Xcode 4.3.2, 先建立一个single view applicatio ...

  2. 【OS_Linux】Linux下软件的安装与卸载

    1.Linux中软件安装包的分类 1) 一类是可执行的软件包,无需编译直接安装.在Windows中所有的软件包都是这种类型.安装完这个程序后,你就可以使用,但你看不到源程序.而且下载时要注意这个软件是 ...

  3. Django ORM操作及进阶

    一般操作 看专业的官网文档,做专业的程序员! 必知必会13条 <1> all(): 查询所有结果 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 ...

  4. module_param

    该宏定义在include/linux/moduleparam.h中 #define ___module_cat(a,b) __mod_ ## a ## b #define __module_cat(a ...

  5. shell中的$(( )) 的用途:主要用在整数的运算$(( a+b*c ))

    $ a=5; b=7; c=2 $ echo $(( a+b*c ))//注意在进行这些运算时必须是双括号 $ echo $(( (a+b)/c )) $ echo $(( (a*b)%c))

  6. ZZULIoj 1912 小火山的爱情密码

    Description 小火山获得了一个字符串,然而大火山让小火山从里面截取一段字符串,并且让小火山截取的字符串满足一些字符达到一定数量. 小火山觉得很容易,但是他想要知道他至少得截取多长的字符串. ...

  7. django基础(web框架,http协议,django安装)

    学习Django之前我们先来看什么是OSI七层模型: 应用层 表示层       应用层(五层模型中把这三层合成一个应用层) http协议 会话层 传输层                  提供端口对 ...

  8. 一款基于jQuery的QQ表情插件

    我们在QQ聊天或者发表评论.微博时,会有一个允许加入表情的功能,点击表情按钮,会弹出一系列表情小图片,选中某个表情图片即可发表的丰富的含表情的内容.今天和大家分享一款基于jQuery的QQ表情插件,您 ...

  9. git删除本地所有的更改

    删除本地所有为暂存的修改: git checkout -f 如果有修改以及加入暂存区的话 那么 使用如下命令: git reset --hard git clean -xdf

  10. Charlie's Change(完全背包记录路径)

    Charlie is a driver of Advanced Cargo Movement, Ltd. Charlie drives a lot and so he often buys coffe ...