华东交通大学2019年ACM 双基 程序设计竞赛

比赛地址

华东交通大学2019年ACM 双基 程序设计竞赛

H谁在说谎(HAOI2011原题:P2519 [HAOI2011]problem a

题目描述

一次考试共有 n 个人参加,可能出现多个人成绩相同的情况。第 i 个人说:“有 ai 个人成绩比我高,bi 个人成绩比我低。”

请求出最少有几个人没有说真话。

输入格式

输入的第一行是一个整数,代表参加考试的人数 n

2 到第 (n+1) 行,每行两个用空格隔开的整数,第 (i+1) 行的两个整数分别代表比第 i 个人成绩高的人数 ai 和比第 i 个人成绩低的人数 bi

输出格式

输出一行一个整数,代表最少有几个人没有说真话。

输入

3 2 0 0 2 2 2

输出

1

说明/提示

对于 100% 的数据,保证 1n1050ai,bin

解题思路

将题意转换:求说真话的最多人数
a 个人成绩比我高,b 个人成绩比我低说明:排名在 a+1nb 的同学的分数一样,设 l=a+1,r=nb,如果 lr 说明此人一定在说假话,不用管,把这些可能说真话的同学的区间提取出来,给每一个区间的初始权值设为 1,如果存在区间(用 ([l,r] 表示)相同,则这些区间权值为相同区间数,表示说这个区间的同学分数相同的有这么多同学,但不应该超过 rl+1 人,因为最多情况是正好说这话的同学排名正好处于该区间内,题目又可转化为在一堆区间中,找出一堆不相交且权值最大的区间。不妨先将右端点排序,使用dp

  • 状态表示:f[i] 表示前 i 个区间中不相交的区间的最大权值和
  • 状态计算:f[i]=max(f[i1],f[k]+b[i].v),其中 k1i1 中满足b[k].r<b[i].l 的最大的 k,正好可以二分找到这样的 k
  • 时间复杂度:O(nlogn)

代码

#include<bits/stdc++.h> using namespace std; const int N=1e5+5; struct Range { int l,r,v; }a[N],b[N]; bool cmp1(Range &a,Range &b) { if(a.l!=b.l)return a.l<b.l; return a.r<b.r; } bool cmp2(Range &a,Range &b) { if(a.r!=b.r)return a.r<b.r; return a.l<b.l; } int n,cnt,m,f[N]; int find(int val,int r) { int l=1; while(l<r) { int mid=l+r+1>>1; if(b[mid].r<val)l=mid; else r=mid-1; } return l; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int l,r; scanf("%d%d",&l,&r); l++,r=n-r; if(l<=r) a[++cnt]={l,r,0}; } sort(a+1,a+1+cnt,cmp1); for(int i=1;i<=cnt;i++) { if(i==1||a[i].l!=a[i-1].l||a[i].r!=a[i-1].r) b[++m]=a[i],b[m].v=1; else if(b[m].v<b[m].r-b[m].l+1)b[m].v++; } sort(b+1,b+1+m,cmp2); f[1]=b[1].v; for(int i=2;i<=m;i++) { int k=find(b[i].l,i-1); f[i]=max(f[i-1],f[k]+b[i].v); } printf("%d",n-f[m]); return 0; }

K.这个勇者明明超强却过分慎重

矩阵乘法模板题~

  • 时间复杂度:O(23×logn)

代码

#include<bits/stdc++.h> using namespace std; const int mod=666666; int n,m; void mul(int f[],int a[][2]) { int c[2]; memset(c,0,sizeof c); for(int i=0;i<2;i++) for(int j=0;j<2;j++) c[i]=(c[i]+1ll*f[j]*a[j][i])%mod; memcpy(f,c,sizeof f); } void mulself(int a[][2]) { int c[2][2]; memset(c,0,sizeof c); for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) c[i][j]=(c[i][j]+1ll*a[i][k]*a[k][j])%mod; memcpy(a,c,sizeof c); } int main() { while(~scanf("%d%d",&n,&m)) { int f[2]={4,233},a[2][2]={{0,3},{1,4}}; n--; for(;n;n>>=1) { if(n&1)mul(f,a); mulself(a); } printf("%d\n",m-f[0]); } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/15562406.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(62)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示