[关闭]
@jerrywcy 2018-08-21T14:02:41.000000Z 字数 14743 阅读 562

南外集训:2018-8-18

南外集训 2018



上午

A题:图的存储和遍历

问题描述:

已知图 G 已用邻接矩阵存储。

(1)编写一个程序,将图 G 转化为邻接表

(2)输出图的深度优先遍历结果 (从节点 1 开始遍历, 序号从小到大)

(3)输出图的广度优先遍历结果(从节点 1 开始遍历, 序号从小到大)

输入文件

第一行:节点总数 n

下面 n 行:图 G 的邻接矩阵

输出文件

第一行:图的深度优先遍历

第二行:图的广度优先遍历

样例:

输入:

8

0 1 1 1 0 0 0 0

1 0 0 0 0 1 0 0

1 0 0 0 1 0 0 0

1 0 0 0 1 1 1 0

0 0 1 1 0 0 0 0

0 1 0 1 0 0 0 0

0 0 0 1 0 0 0 1

0 0 0 0 0 0 1 0

输出:

1 2 6 4 5 3 7 8

1 2 3 4 6 5 7 8

(模板题你还想要题目链接?!)

题解

模板啊模板

贴代码:

  1. #include<bits\stdc++.h>
  2. #define fz1(i,n) for ((i)=1;(i)<=(n);(i)++)
  3. using namespace std;
  4. int n,m,i,j,mp[1005][1005],vis[1005],cnt;
  5. vector<int> bi[1005];
  6. void dfs(int x)
  7. {
  8. if (vis[x]) return;
  9. vis[x]=1;
  10. printf("%d%c",x,((++cnt)==n?'\n':' '));
  11. int i;
  12. for (i=0;i<bi[x].size();i++) dfs(bi[x][i]);
  13. }
  14. void bfs()
  15. {
  16. queue<int> qx;
  17. vis[1]=1;
  18. qx.push(1);
  19. while (!qx.empty())
  20. {
  21. int x=qx.front();qx.pop();
  22. printf("%d%c",x,((++cnt)==n?'\n':' '));
  23. for (i=0;i<bi[x].size();i++) if (!vis[bi[x][i]])
  24. {
  25. vis[bi[x][i]]=1;
  26. qx.push(bi[x][i]);
  27. }
  28. }
  29. }
  30. int main()
  31. {
  32. scanf("%d",&n);
  33. fz1(i,n) fz1(j,n)
  34. {
  35. scanf("%d",&mp[i][j]);
  36. if (mp[i][j]) bi[i].push_back(j);
  37. }
  38. dfs(1);
  39. cnt=0;
  40. memset(vis,0,sizeof(vis));
  41. bfs();
  42. return 0;
  43. }

B题:家庭问题

问题描述:

有 n 个人,编号分别为 1,2,…n,另外还知道存在 k 个关系。一个关系的表达为二元组(α,β)形式,表示 α,β
为同一家庭的成员。

问题: 当 n,k 和 k 个关系给出之后,求出其中共有多少个家庭、 最大的家庭中有多少人。

例如:n=6,k=3,三个关系为:(1,2),(1,3),(4,5)

此时,6 个人组成三个家庭,即:{1,2,3}为一个家庭,{4,5}为一个家庭,{6}单独为一个家庭,第一个家庭的人数最多。

输入文件

输入的第一行为 n,k 二个整数(0≤n≤100) (用空格分隔) ,接下来的 k 行, 每行二个整数 (用空格分隔)表示关系。

输出文件

二个整数(分别表示家庭个数和最大家庭人数)

样例:

输入:

6 3

1 2

1 3

4 5

输出:

3 3

题解

并查集模板题

贴代码:

  1. #include<bits\stdc++.h>
  2. #define fz1(i,n) for ((i)=1;(i)<=(n);(i)++)
  3. using namespace std;
  4. int n,m,i,j,fa[105],x,y,cnt[105],s1,s2;
  5. int fnd(int x)
  6. {
  7. if (fa[x]==x) return x;
  8. return fa[x]=fnd(fa[x]);
  9. }
  10. int main()
  11. {
  12. scanf("%d%d",&n,&m);
  13. fz1(i,n) fa[i]=i;
  14. fz1(i,m)
  15. {
  16. scanf("%d%d",&x,&y);
  17. fa[fnd(x)]=fnd(y);
  18. }
  19. fz1(i,n) cnt[fnd(i)]++;
  20. fz1(i,n) if (cnt[i])
  21. {
  22. s1++;
  23. s2=max(s2,cnt[i]);
  24. }
  25. printf("%d %d\n",s1,s2);
  26. return 0;
  27. }

C题:无线电通讯网

问题描述:国防部计划用无线网络连接若干个边防哨所。2 种不同的通讯技术用来搭建无线网络:每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话。

任意两个配备了一条卫星电话线路的哨所均可以通话,无论它们相距多远。 而只通过无线电收发器通话的哨所之间的距离不能超过 ,这是受收发器的功率限制。

收发器的功率越高,通话距离 会更远,但同时价格也更贵。
收发器需要统一购买和安装,所以全部哨所只能选择安装一种型号的收发器。 换句话说,每一对哨所之间的通话距离都是同一个
你的任务是确定收发器必须的最小通话距离,使得每一对哨所之间至少有一条通话路径(直接的或者间接的) 。

输入文件

第 1 行:2 个整数 )和 ),表示可安装的卫星电话的线路数,表示边防哨所的数量。

接下来 行,每行描述一个哨所的平面坐标,以 km 为单位,整数,

输出文件

第 1 行:1 个实数,表示无线电收发器的最小传输距离。精确到小数点后两位。

样例:

输入:

2 4

0 100

0 300

0 600

150 750

输出:
212.13

题解

最小生成树中最长边即为答案。

贴上代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int s,p;
  4. double minn[505],dis[505][505];
  5. struct point
  6. {
  7. int x;
  8. int y;
  9. };
  10. double dist(point a,point b)
  11. {
  12. return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));
  13. }
  14. int comp(int a,int b)
  15. {
  16. return a>b;
  17. }
  18. point a[505];
  19. bool u[505];
  20. int main()
  21. {
  22. int i,j;
  23. cin>>s>>p;
  24. for(i=1;i<=p;i++)
  25. cin>>a[i].x>>a[i].y;
  26. for(i=1;i<=p;i++)
  27. for(j=1;j<=p;j++)
  28. dis[i][j]=dist(a[i],a[j]);
  29. memset(minn,0x7f,sizeof(minn));
  30. minn[1]=0;
  31. memset(u,1,sizeof(u));
  32. for(i=1;i<=p;i++)
  33. {
  34. int k=0;
  35. for(j=0;j<=p;j++)
  36. if(u[j]&&(minn[j]<minn[k]))
  37. k=j;
  38. u[k]=0;
  39. for(j=1;j<=p;j++)
  40. if(u[j] && dis[k][j]<minn[j])
  41. minn[j]=dis[k][j];
  42. }
  43. sort(minn+1,minn+p+1,comp);
  44. cout<<setprecision(2)<<fixed<<minn[s]<<endl;
  45. return 0;
  46. }

D题:最小差值生成树

问题描述

MST(最小生成树)是图论中的一类非常重要的问题。对你来说可能已经非常容易了。

给出一个带权图 G(V,E),最小生成树T是图G的一棵子树。问题是:输出图的最小生成树中最长边与最短边的差。

输入文件

第一行两个数 N()和(), 表示图中点的个数和边的条数。

接下来有 M 行,第 i 行有三个整数 (),(),(),表示 的一条边,权值为 ,图中任意两点间最多一条边。

输出文件:

一行,一个数,表示最小生成树中最大权值与最小权值的差。

样例:

输入:

3 3

1 2 10

1 3 20

2 3 30

输出:

10

题解

最小生成树模板+最长边减最短边=题解

贴代码:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <climits>
  5. const int maxn = 105;
  6. const int maxm = 10005;
  7. int par[maxn],rank[maxn];
  8. struct edge
  9. {
  10. int from;
  11. int to;
  12. int dis;
  13. };
  14. edge edges[maxm];
  15. int n,m;
  16. void init()
  17. {
  18. int i;
  19. for(i=0;i<=n;i++){
  20. par[i]=i;
  21. rank[i]=0;
  22. }
  23. }
  24. int find(int x)
  25. {
  26. return par[x] == x ? x : par[x] = find(par[x]);
  27. }
  28. void unite(int x,int y)
  29. {
  30. x=find(x);
  31. y=find(y);
  32. if(x==y) return ;
  33. if(rank[x]<rank[y])
  34. par[x]=y;
  35. else{
  36. par[y]=x;
  37. if(rank[x]==rank[y])
  38. rank[x]++;
  39. }
  40. }
  41. bool cmp(edge a,edge b)
  42. {
  43. return a.dis<b.dis;
  44. }
  45. bool same(int x,int y)
  46. {
  47. return find(x)==find(y);
  48. }
  49. int Kruskal()
  50. {
  51. int ans=INT_MAX/10;
  52. std::sort(edges+1,edges+1+m,cmp);
  53. bool flag=0;
  54. int i,j;
  55. for(i=1;i<=m;i++){
  56. init();
  57. int l,r;
  58. l=r=edges[i].dis;
  59. int cnt=0;
  60. unite(edges[i].from,edges[i].to);
  61. cnt++;
  62. for(j=i+1;j<=m;j++){
  63. if(!same(edges[j].from,edges[j].to)){
  64. unite(edges[j].from,edges[j].to);
  65. cnt++;
  66. r=std::max(r,edges[j].dis);
  67. }
  68. }
  69. if(cnt==n-1){
  70. ans=std::min(ans,r-l);
  71. flag=1;
  72. }
  73. }
  74. if(!flag) ans=-1;
  75. return ans;
  76. }
  77. int main()
  78. {
  79. scanf("%d %d",&n,&m);
  80. int i,j;
  81. for(i=1;i<=m;i++)
  82. scanf("%d %d %d",&edges[i].from,&edges[i].to,&edges[i].dis);
  83. printf("%d\n",Kruskal());
  84. return 0;
  85. }

E题:传话

问题描述

兴趣小组的同学来自各个学校,为了增加友谊,晚会上又进行了一个传话游戏,

如果认识,那么 收到某个消息,就会把这个消息传给,以及所有 认识的人。如果认识不一定认识

所有人从编号,给出所有“认识”关系,问如果 发布一条新消息,那么会不会经过若干次传话后,这个消息传回给了

输入文件

输入的第一行是两个数()和 (), 两数之间有一个空格,表示人数和认识关系数。

接下来的行,每行两个数,表示认识, 。认识关系可能会重复给出,但一行的两个数不会相同。

输出文件

输出一共有行,每行一个字符 T 或 F。第行如果是 T,表示发出一条新消息会传回给;如果是 F,表示 发出一条新消息不会传回给

样例:

输入:

4 6

1 2

2 3

4 1

3 1

1 3

2 3

输出:

T

T

T

F

题解

我一开始还以为有多复杂其实只要暴搜就好了啊哈哈哈哈(我试图用不加句读的方式来掩饰尴尬)

贴代码:

  1. #include<bits\stdc++.h>
  2. #define fz1(i,n) for ((i)=1;(i)<=(n);(i)++)
  3. #define sqr(x) (x)*(x)
  4. using namespace std;
  5. int n,m,i,j,vis[1005],x,y;
  6. vector<int> bi[1005];
  7. void dfs(int x)
  8. {
  9. int i;
  10. for (i=0;i<bi[x].size();i++)
  11. {
  12. if (vis[bi[x][i]]) continue;
  13. vis[bi[x][i]]=1;
  14. dfs(bi[x][i]);
  15. }
  16. }
  17. int main()
  18. {
  19. cin>>n>>m;
  20. fz1(i,m)
  21. {
  22. cin>>x>>y;
  23. bi[x].push_back(y);
  24. }
  25. fz1(i,n)
  26. {
  27. memset(vis,0,sizeof(vis));
  28. dfs(i);
  29. if (vis[i]) puts("T"); else puts("F");
  30. }
  31. return 0;
  32. }

下午

A题 A Pie for a Pie

题意翻译

Bessie和Elsie都会烤N个派()。是Bessie和Elsie口味不同,每个派都有两个美味值,分别是Bessie和Elsie的。

Bessie想给Elsie一个她的派。如果Elsie从Bessie那里收到一个派,她会觉得自己有义务给Bessie一个派,比如美味值为x。这样就不会显得小气、Elsie会挑一种派,至少是比她收到的派好吃的(在Elsie看来),但又美味值不增加D单位(),也就是[x,x+D]范围内的。这个派可能不存在,在这种情况下,Elsie将使用一个化名,把自己放逐到日本去。

但如果Elsie不给Bessie回赠一个馅饼,Bessie同样会给Elsie一个馅饼,这个派好吃但美味值不增加D单位(在Bessie眼中)。如果这是不可能的,Bessie也会放逐自己,否则她会将她选择的派给Elsie。这个循环将持续到一头牛被放逐,或一头牛收到一个价值为0(在她自己看来)的派,此时交换结束,两只奶牛都会很快乐。

请注意,一个馅饼不会被送两次,任意一只牛也不能把馅饼送给她自己。

Bessie可以选择她最初送给Elsie的礼物,请确定在交换结束之前,两只奶牛的交换次数。

感谢 @wflengxuenong 提供的翻译。

题目描述

Bessie and Elsie have each baked pies (). Each of the 2N2N2N pies has a tastiness value according to Bessie and a (possibly different) tastiness value according to Elsie.

Bessie is thinking about giving one of her pies to Elsie. If Elsie receives a pie from Bessie, she will feel obligated to give one of her pies to Bessie. So as to not appear stingy nor flamboyant, Elsie will try to pick a pie that is at least as tasty (in Elsie's eyes) as the pie she received, but no more than units tastier (). Such a pie may not exist, in which case Elsie will adopt a pseudonym and exile herself to Japan.

But if Elsie does give Bessie a pie in return, Bessie will similarly try to give Elsie a pie which is at least as tasty but no more than units tastier (in Bessie's eyes) as the pie Elsie just gave her. Should this be impossible, Bessie too will exile herself. Otherwise she will give her chosen pie to Elsie. This cycle will continue until one of the cows is exiled, an unhappy outcome, or one of the cows receives a pie which she accords a tastiness value of , in which case the gift exchange will end and both cows will be happy.

Note that a pie may not be gifted twice, nor can either cow return a pie gifted to her.

For each of the pies Bessie could select as her initial gift to Elsie, determine the minimum number of pies that could possibly be gifted in the resulting exchange before the cows are happy.

输入输出格式

输入格式:

The first line contains the two integers NNN and DDD .

The next lines contain two space-separated integers each, respectively denoting the value of a particular pie according to Bessie, and the value of that pie according to Elsie.

The first lines refer to Bessie's pies, and the remaining lines refer to Elsie's pies.

It is guaranteed that all tastiness values are in the range .

输出格式:

There should be lines in the output. Line iii should contain a single integer: the minimum number of pies that could be gifted in a happy gift exchange started with Bessie's pie . If no gift exchange starting with pie iii is happy, then line iii should contain the single integer instead.

输入输出样例

输入样例#1:

2 1
1 1
5 0
4 2
1 4

输出样例#1:

3
1

题目链接

题解

思路是建图,然后bfs

对于pie #u,和每一个一方给出#u后可以回赠的pie #v,连接单向边(v,u)。

定义dis数组,dis[i]表示从pie #i开始,最少交换多少次pie可以达到happy ending。

对于每一个属于一方,但对另一方的价值是0的pie #i,dis[i]=1。余下的都是-1。

然后bfs,如果下家dis值是-1就用当前dis值去更新,并把下家加入队列(突然发现这就是个spfa)。

贴代码:

  1. #include <bits/stdc++.h>
  2. #define pb push_back
  3. using namespace std;
  4. struct node{
  5. int b,e,id;
  6. }bs[200010],el[200010];
  7. int n,d;
  8. vector<int> g[200010];
  9. int dis[200010];
  10. queue<int> q;
  11. bool cmpb(node x,node y){
  12. return x.b<y.b;
  13. }
  14. bool cmpe(node x,node y){
  15. return x.e<y.e;
  16. }
  17. void build(){//建图
  18. sort(bs+1,bs+2*n+1,cmpb);
  19. sort(el+1,el+2*n+1,cmpe);//排序
  20. int i,j;
  21. //对于每一个Bessie可能送来的pie #u,考虑所有满足v.e>u.e的pie #v,连接单向边(v,u)。
  22. for (i=1;i<=2*n;i++){
  23. int u=el[i].id;
  24. if (u>n || el[i].e==0)continue;
  25. for (j=i-1;j>1;j--)if (el[j].e<el[i].e)break;//找到分界点,因为排过序,所以分界点之后的都是满足条件的
  26. if (j<1)j=1;
  27. for (;j<=2*n;j++){
  28. if (el[j].e<el[i].e)continue;
  29. if (el[j].e>el[i].e+d)break;
  30. int v=el[j].id;
  31. if (v>n)g[v].pb(u);//连接单向边(v,u)。
  32. }
  33. }
  34. //和上面那段差不多
  35. for (i=1;i<=2*n;i++){
  36. int u=bs[i].id;
  37. if (u<=n || bs[i].b==0)continue;
  38. for (j=i-1;j>1;j--)if (bs[j].b<bs[i].b)break;
  39. if (j<1)j=1;
  40. for (;j<=2*n;j++){
  41. if (bs[j].b<bs[i].b)continue;
  42. if (bs[j].b>bs[i].b+d)break;
  43. int v=bs[j].id;
  44. if (v<=n)g[v].pb(u);
  45. }
  46. }
  47. }
  48. void bfs(){//spfa?
  49. int i,j;
  50. while (!q.empty()){
  51. int u=q.front();
  52. q.pop();
  53. for (i=0;i<g[u].size();i++){
  54. int v=g[u][i];
  55. if (dis[v]!=-1)continue;
  56. dis[v]=dis[u]+1;//用dis[u]更新dis[v]
  57. q.push(v);//v入队
  58. }
  59. }
  60. }
  61. int main()
  62. {
  63. cin>>n>>d;
  64. int i,j;
  65. memset(dis,-1,sizeof(dis));//dis数组初始化
  66. for (i=1;i<=2*n;i++){
  67. int x,y;
  68. cin>>x>>y;
  69. bs[i]={x,y,i};
  70. el[i]={x,y,i};
  71. if ((i<=n && y==0) || (i>n && x==0))dis[i]=1,q.push(i);//边界条件
  72. }
  73. build();
  74. bfs();
  75. for (i=1;i<=n;i++)cout<<dis[i]<<endl;
  76. return 0;
  77. }

B题: Barn Painting

题意翻译

题意:给定一颗N个节点组成的树,3种颜色,其中K个节点已染色,要求任意两相邻节点颜色不同,求合法染色方案数。

翻译贡献者:Il_ItzABC_lI

题目描述

Farmer John has a large farm with barns(), some of which are already painted and some not yet painted. Farmer John wants to paint these remaining barns so that all the barns are painted, but he only has three paint colors available. Moreover, his prize cow Bessie becomes confused if two barns that are directly reachable from one another are the same color, so he wants to make sure this situation does not happen.

It is guaranteed that the connections between the NNN barns do not form any 'cycles'. That is, between any two barns, there is at most one sequence of connections that will lead from one to the other.

How many ways can Farmer John paint the remaining yet-uncolored barns?

输入输出格式

输入格式:

The first line contains two integers and (), respectively the number of barns on the farm and the number of barns that have already been painted.

The next N−1N-1N−1 lines each contain two integers and () describing a path directly connecting barns xxx and yyy .

The next KKK lines each contain two integers and () indicating that barn is painted with color ccc .

输出格式:

Compute the number of valid ways to paint the remaining barns, modulo , such that no two barns which are directly connected are the same color.

输入输出样例

输入样例#1:

4 1
1 2
1 3
1 4
4 3

输出样例#1:

8

题目链接

题解

这是一道树形dp

状态转移方程不太好写,贴代码核心部分好了

  1. void dfs(int x,int fa){
  2. f[x][1]=f[x][2]=f[x][3]=1;//边界
  3. int i,j;
  4. int y,tmp;
  5. for (i=0;i<g[x].size();i++){//遍历所有子节点
  6. int y=g[x][i];
  7. if (y==fa)continue;//如果是父节点就跳过
  8. dfs(y,x);
  9. tmp=add(f[y][1],add(f[y][2],f[y][3]));//所有颜色的方案数之和
  10. for (j=1;j<=3;j++)
  11. f[x][j]=f[x][j]*(long long)add(tmp,mod-f[y][j])%mod;//每一种颜色乘以子节点中另外两种颜色的方案数之和
  12. }
  13. if (color[x])//如果当前节点的颜色已经指定
  14. for (i=1;i<=3;i++)
  15. if (i!=color[x])
  16. f[x][i]=0;//别的颜色的方案数为0
  17. }

完整代码:

  1. #include <bits/stdc++.h>
  2. #define pb push_back
  3. using namespace std;
  4. const int mod=1e9+7;
  5. int n,k;
  6. vector<int> g[100010];
  7. int color[100010];
  8. long long f[100010][4];
  9. int add(int x,int y){
  10. x+=y;
  11. if (x>=mod)return x-mod;
  12. else return x;
  13. }
  14. void dfs(int x,int fa){
  15. f[x][1]=f[x][2]=f[x][3]=1;
  16. int i,j;
  17. int y,tmp;
  18. for (i=0;i<g[x].size();i++){
  19. int y=g[x][i];
  20. if (y==fa)continue;
  21. dfs(y,x);
  22. tmp=add(f[y][1],add(f[y][2],f[y][3]));
  23. for (j=1;j<=3;j++)
  24. f[x][j]=f[x][j]*(long long)add(tmp,mod-f[y][j])%mod;
  25. }
  26. if (color[x])
  27. for (i=1;i<=3;i++)
  28. if (i!=color[x])
  29. f[x][i]=0;
  30. }
  31. int main()
  32. {
  33. cin>>n>>k;
  34. int i,j;
  35. for (i=1;i<n;i++){
  36. int u,v;
  37. cin>>u>>v;
  38. g[u].pb(v);
  39. g[v].pb(u);
  40. }
  41. for (i=1;i<=k;i++){
  42. int b,c;
  43. cin>>b>>c;
  44. color[b]=c;
  45. }
  46. dfs(1,0);
  47. cout<<add(f[1][1],add(f[1][2],f[1][3]))<<endl;
  48. return 0;
  49. }

C题 Haybale Feast

题意翻译

题意:给定2个由N个数字组成的数列 , ,需要找到使得 , 并输出在所有满足条件的,中, 的最小值。

翻译贡献者:Il_ItzABC_lI

题目描述

Farmer John is preparing a delicious meal for his cows! In his barn, he has NNN haybales (). The iii th haybale has a certain flavor ​ () and a certain spiciness SiS_iSi​( ).

The meal will consist of a single course, being a contiguous interval containing one or more consecutive haybales (Farmer John cannot change the order of the haybales). The total flavor of the meal is the sum of the flavors in the interval. The spiciness of the meal is the maximum spiciness of all haybales in the interval.

Farmer John would like to determine the minimum spiciness his single-course meal could achieve, given that it must have a total flavor of at least ().

输入输出格式

输入格式:

The first line contains the integers and , the number of haybales and the minimum total flavor the meal must have, respectively. The next lines describe the haybales with two integers per line, first the flavor and then the spiciness .

输出格式:

Please output the minimum spiciness in a single course meal that satisfies the minimum flavor requirement. There will always be at least one single-course meal that satisfies the flavor requirement.

输入输出样例

输入样例#1:

5 10
4 10
6 15
3 5
4 9
3 6

输出样例#1:

9

题目链接

题解

这题比较简单,连我这样的菜鸡都能AC。。。

两个指针l,r,如果当前总风味不到m,r++,反之l++。其中总辣度用单调队列维护。

据说还有一种线段树解法,不过我没去想。。。

单调队列:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. struct num{
  4. int x,i;
  5. };
  6. class simple_queue{
  7. public:
  8. num a[100010];
  9. int l,r;
  10. void clear(){
  11. memset(a,0,sizeof(a));
  12. l=1,r=0;
  13. }
  14. void push(int x,int i){
  15. while (a[r].x<x && r>=l)r--;
  16. r++;
  17. a[r].x=x,a[r].i=i;
  18. }
  19. void pop(int t){
  20. while (a[l].i<t && l<=r)l++;
  21. }
  22. int front(){
  23. return a[l].x;
  24. }
  25. };
  26. long long n,m;
  27. int f[100010],s[100010];
  28. int ans=-1;
  29. int main()
  30. {
  31. cin>>n>>m;
  32. int i,j;
  33. for (i=1;i<=n;i++){
  34. cin>>f[i]>>s[i];
  35. }
  36. long long l,r,sumf;
  37. l=1,r=1,sumf=0;
  38. simple_queue sums;
  39. sums.clear();
  40. while (r<=n){
  41. while (sumf<m && r<=n){
  42. sumf+=f[r];
  43. sums.push(s[r],r);
  44. r++;
  45. }
  46. if (sumf>=m){
  47. if (ans!=-1)ans=min(ans,sums.front());
  48. else ans=sums.front();
  49. // cout<<l<<' '<<r<<' '<<ans<<endl;
  50. }
  51. while (sumf>=m && l<r){
  52. l++;
  53. sumf-=f[l];
  54. }
  55. sums.pop(l);
  56. }
  57. cout<<ans<<endl;
  58. return 0;
  59. }

线段树代码:

  1. //按b从小到大排序,然后按顺序往里扔,维护最大子段和,如果合法了即得到答案。
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. #define ll long long
  5. #define inf 0x3f3f3f3f
  6. #define N 100010
  7. #define pa pair<int,int>
  8. inline char gc(){
  9. static char buf[1<<16],*S,*T;
  10. if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
  11. return *S++;
  12. }
  13. inline ll read(){
  14. ll x=0,f=1;char ch=gc();
  15. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
  16. while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
  17. return x*f;
  18. }
  19. int n;
  20. ll K;
  21. struct hhh{
  22. int a,b,id;
  23. friend bool operator<(hhh a,hhh b){return a.b<b.b;}
  24. }a[N];
  25. struct node{
  26. ll ls,rs,s;bool cov;
  27. }tr[N<<2];
  28. inline void update(int p){
  29. if(tr[p<<1].cov&&tr[p<<1|1].cov){
  30. tr[p].cov=1;tr[p].ls=tr[p].rs=tr[p].s=tr[p<<1].s+tr[p<<1|1].s;return;
  31. }tr[p].ls=tr[p<<1].ls;tr[p].rs=tr[p<<1|1].rs;
  32. if(tr[p<<1].cov) tr[p].ls+=tr[p<<1|1].ls;
  33. if(tr[p<<1|1].cov) tr[p].rs+=tr[p<<1].rs;
  34. tr[p].s=max(tr[p<<1].s,tr[p<<1|1].s);
  35. tr[p].s=max(tr[p].s,tr[p<<1].rs+tr[p<<1|1].ls);
  36. }
  37. inline void build(int p,int l,int r){
  38. tr[p].ls=tr[p].rs=tr[p].s=tr[p].cov=0;
  39. if(l==r) return;
  40. int mid=l+r>>1;
  41. build(p<<1,l,mid);
  42. sbuild(p<<1|1,mid+1,r);
  43. }
  44. inline void ins(int p,int l,int r,int x,int val){
  45. if(l==r){tr[p].ls=tr[p].rs=tr[p].s=val;tr[p].cov=1;return;}
  46. int mid=l+r>>1;
  47. if(x<=mid) ins(p<<1,l,mid,x,val);
  48. else ins(p<<1|1,mid+1,r,x,val);update(p);
  49. }
  50. int main(){
  51. n=read();K=read();
  52. for(int i=1;i<=n;++i) a[i].a=read(),a[i].b=read(),a[i].id=i;
  53. sort(a+1,a+n+1);build(1,1,n);int ans=0;
  54. for(int i=1;i<=n;++i){
  55. ins(1,1,n,a[i].id,a[i].a);
  56. if(tr[1].s>=K){ans=a[i].b;break;}
  57. }printf("%d\n",ans);
  58. return 0;
  59. }

完毕

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注