A.第k小数
题意:
给
一
个
长
度
为
n
的
数
列
,
找
出
第
k
小
数
给一个长度为n的数列,找出第k小数
给一个长度为n的数列,找出第k小数
题解:
本
来
是
一
个
签
到
题
,
结
果
数
据
范
围
给
出
了
本来是一个签到题,结果数据范围给出了
本来是一个签到题,结果数据范围给出了
大
批
的
w
a
就
出
现
了
大批的wa就出现了
大批的wa就出现了
最
后
n
<
=
5
e
6
,
直
接
快
读
加
s
o
r
t
找
a
k
就
行
最后n<=5e6,直接快读加sort找a_k就行
最后n<=5e6,直接快读加sort找ak就行
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=4e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int a[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int _;
while(cin>>_){
while(_--){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+1+n);
cout<<a[k]<<endl;
}
}
return 0;
}
B.不平行的直线
题意:
有
n
个
不
重
复
点
,
任
意
两
个
点
可
以
组
成
线
段
有n个不重复点,任意两个点可以组成线段
有n个不重复点,任意两个点可以组成线段
能
找
出
最
多
多
少
条
线
段
不
互
相
平
行
或
重
合
能找出最多多少条线段不互相平行或重合
能找出最多多少条线段不互相平行或重合
题解:
由
于
几
条
线
平
行
只
能
选
一
条
由于几条线平行只能选一条
由于几条线平行只能选一条
所
以
直
接
看
每
条
线
的
斜
率
所以直接看每条线的斜率
所以直接看每条线的斜率
如
果
重
复
出
现
,
那
么
后
面
的
就
不
能
被
继
续
选
中
如果重复出现,那么后面的就不能被继续选中
如果重复出现,那么后面的就不能被继续选中
最
直
接
的
方
法
,
s
e
t
存
斜
率
,
判
一
下
斜
率
不
存
在
的
情
况
是
否
出
现
最直接的方法,set存斜率,判一下斜率不存在的情况是否出现
最直接的方法,set存斜率,判一下斜率不存在的情况是否出现
如
果
出
现
,
不
管
几
次
都
加
1
,
然
后
看
s
e
t
.
s
i
z
e
(
)
如果出现,不管几次都加1,然后看set.size()
如果出现,不管几次都加1,然后看set.size()
但
是
斜
率
会
出
现
小
数
,
需
要
用
d
o
u
b
l
e
,
s
e
t
可
能
会
被
卡
精
度
(
这
道
题
没
有
)
但是斜率会出现小数,需要用double,set可能会被卡精度(这道题没有)
但是斜率会出现小数,需要用double,set可能会被卡精度(这道题没有)
所
以
可
以
取
出
所
有
斜
率
,
排
序
一
下
,
自
己
手
动
判
重
所以可以取出所有斜率,排序一下,自己手动判重
所以可以取出所有斜率,排序一下,自己手动判重
手
动
用
x
−
y
<
e
p
s
判
相
等
不
会
出
现
被
卡
精
度
的
情
况
手动用x-y<eps判相等不会出现被卡精度的情况
手动用x−y<eps判相等不会出现被卡精度的情况
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
double x[210],y[210];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>x[i]>>y[i];
set<double> s;
int f=0;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++){
if(!(y[i]-y[j])){f=1;continue;}
s.insert((x[i]-x[j])/(y[i]-y[j]));
}
cout<<s.size()+f;
return 0;
}
C. 丢手绢
题意:
n
个
小
朋
友
围
成
一
个
圈
,
给
出
相
邻
两
个
小
朋
友
的
距
离
n个小朋友围成一个圈,给出相邻两个小朋友的距离
n个小朋友围成一个圈,给出相邻两个小朋友的距离
最
后
问
任
意
两
个
小
朋
友
的
最
远
距
离
最后问任意两个小朋友的最远距离
最后问任意两个小朋友的最远距离
题解:
直
接
操
作
可
以
是
枚
举
任
意
两
个
小
朋
友
,
看
他
俩
的
距
离
直接操作可以是枚举任意两个小朋友,看他俩的距离
直接操作可以是枚举任意两个小朋友,看他俩的距离
但
是
这
样
会
超
时
但是这样会超时
但是这样会超时
从
一
个
朋
友
的
左
边
出
发
到
右
边
,
每
个
小
朋
友
和
他
的
距
离
一
定
是
个
凸
函
数
从一个朋友的左边出发到右边,每个小朋友和他的距离一定是个凸函数
从一个朋友的左边出发到右边,每个小朋友和他的距离一定是个凸函数
所
以
可
以
考
虑
三
分
,
对
每
个
小
朋
友
进
行
三
分
找
最
远
距
离
所以可以考虑三分,对每个小朋友进行三分找最远距离
所以可以考虑三分,对每个小朋友进行三分找最远距离
通
过
前
缀
和
维
护
任
意
两
个
小
朋
友
直
接
的
距
离
通过前缀和维护任意两个小朋友直接的距离
通过前缀和维护任意两个小朋友直接的距离
环
的
距
离
有
两
个
方
向
,
所
以
要
记
得
两
个
方
向
取
距
离
环的距离有两个方向,所以要记得两个方向取距离
环的距离有两个方向,所以要记得两个方向取距离
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
ll i,a[maxn];
ll s[maxn],sum;
ll check(ll x){
ll y=s[x]-s[i-1];
return min(y,sum-y);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;cin>>n;
for(i=1;i<=n;i++)
cin>>a[i],sum+=a[i];
for(i=1;i<=2*n;i++){
if(i<=n)s[i]=s[i-1]+a[i];
else s[i]=s[i-1]+a[i-n];
}
ll ans=0;
for(i=1;i<=n;i++){
ll l=i,r=i+n;
while(l+10<r){
ll lm=l+(r-l)/3,rm=r-(r-l)/3;
if(check(lm)>=check(rm))r=rm;
else l=lm;
}
for(ll j=l;j<=r;j++)
ans=max(ans,check(j));
}
cout<<ans;
return 0;
}
D. 二分
题意:
猜
数
游
戏
,
你
猜
一
个
数
,
裁
判
告
诉
你
答
案
比
这
个
数
大
还
是
小
或
等
于
猜数游戏,你猜一个数,裁判告诉你答案比这个数大还是小或等于
猜数游戏,你猜一个数,裁判告诉你答案比这个数大还是小或等于
但
是
裁
判
会
忘
记
了
自
己
说
的
但是裁判会忘记了自己说的
但是裁判会忘记了自己说的
所
以
裁
判
说
的
不
一
定
正
确
,
告
诉
你
n
条
裁
判
说
的
所以裁判说的不一定正确,告诉你n条裁判说的
所以裁判说的不一定正确,告诉你n条裁判说的
判
断
裁
判
说
的
是
正
确
的
可
能
有
几
句
判断裁判说的是正确的可能有几句
判断裁判说的是正确的可能有几句
题解:
这
个
总
容
易
想
到
的
就
是
枚
举
这
个
数
这个总容易想到的就是枚举这个数
这个总容易想到的就是枚举这个数
但
是
这
个
数
太
大
,
是
在
i
n
t
范
围
内
的
所
有
数
但是这个数太大,是在int范围内的所有数
但是这个数太大,是在int范围内的所有数
所
以
可
能
会
想
到
三
分
,
但
是
通
过
自
己
写
几
个
数
据
实
验
一
下
所以可能会想到三分,但是通过自己写几个数据实验一下
所以可能会想到三分,但是通过自己写几个数据实验一下
发
现
并
不
是
一
个
凸
函
数
发现并不是一个凸函数
发现并不是一个凸函数
所
以
我
们
就
考
虑
用
差
分
来
做
,
去
计
数
每
一
条
正
确
的
区
间
所以我们就考虑用差分来做,去计数每一条正确的区间
所以我们就考虑用差分来做,去计数每一条正确的区间
由
于
数
较
大
,
所
以
要
进
行
离
散
,
将
给
出
的
数
和
左
右
相
邻
的
数
一
起
离
散
由于数较大,所以要进行离散,将给出的数和左右相邻的数一起离散
由于数较大,所以要进行离散,将给出的数和左右相邻的数一起离散
如
果
答
案
大
于
某
个
数
,
把
这
个
数
对
于
的
离
散
后
的
位
置
右
边
用
差
分
加
一
如果答案大于某个数,把这个数对于的离散后的位置右边用差分加一
如果答案大于某个数,把这个数对于的离散后的位置右边用差分加一
相
等
就
是
这
个
点
加
一
,
小
于
的
话
同
理
大
于
的
情
况
相等就是这个点加一,小于的话同理大于的情况
相等就是这个点加一,小于的话同理大于的情况
最
后
统
计
每
个
数
的
正
确
情
况
,
找
到
最
大
的
最后统计每个数的正确情况,找到最大的
最后统计每个数的正确情况,找到最大的
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int n;
ll x[maxn],a[maxn],c[maxn];
char y[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>n;
int len=0;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
c[++len]=x[i];
c[++len]=x[i]-1;
c[++len]=x[i]+1;
}
sort(c+1,c+1+len);
len=unique(c+1,c+1+len)-c-1;
for(int i=1;i<=n;i++){
int p=lower_bound(c+1,c+1+len,x[i])-c;
if(y[i]=='.')a[p]++,a[p+1]--;
if(y[i]=='-')a[p+1]++,a[len+10]--;
if(y[i]=='+')a[1]++,a[p]--;
}
ll ans=0;
for(int i=1;i<=len+10;i++)
a[i]+=a[i-1],ans=max(ans,a[i]);
cout<<ans;
return 0;
}
E. 交换
题意:
有
n
个
无
序
的
数
,
通
过
最
少
多
少
次
交
换
可
以
使
他
有
序
有n个无序的数,通过最少多少次交换可以使他有序
有n个无序的数,通过最少多少次交换可以使他有序
题解:
交
换
数
,
最
差
情
况
是
n
次
,
把
每
个
数
交
换
到
对
应
的
位
置
交换数,最差情况是n次,把每个数交换到对应的位置
交换数,最差情况是n次,把每个数交换到对应的位置
但
是
如
果
出
现
如
下
情
况
但是如果出现如下情况
但是如果出现如下情况
比
如
数
列
1
,
4
,
2
,
3
,
5
,
6
比如数列1,4,2,3,5,6
比如数列1,4,2,3,5,6
这
里
的
4
,
3
,
2
。
2
的
位
置
放
着
4
,
4
的
位
置
放
着
3
,
3
的
位
置
放
着
2
这里的4,3,2。2的位置放着4,4的位置放着3,3的位置放着2
这里的4,3,2。2的位置放着4,4的位置放着3,3的位置放着2
这
样
称
为
一
个
循
环
节
,
只
要
2
和
4
换
,
3
和
4
换
就
可
以
了
这样称为一个循环节,只要2和4换,3和4换就可以了
这样称为一个循环节,只要2和4换,3和4换就可以了
循
环
节
有
x
个
数
,
只
要
换
x
−
1
个
数
就
可
以
让
所
有
数
都
归
位
循环节有x个数,只要换x-1个数就可以让所有数都归位
循环节有x个数,只要换x−1个数就可以让所有数都归位
所
以
就
是
,
有
几
个
循
环
节
就
可
以
少
换
几
次
所以就是,有几个循环节就可以少换几次
所以就是,有几个循环节就可以少换几次
总
共
是
n
次
,
那
么
最
后
结
果
就
是
用
n
−
循
环
节
数
总共是n次,那么最后结果就是用n-循环节数
总共是n次,那么最后结果就是用n−循环节数
然
后
需
要
找
循
环
节
然后需要找循环节
然后需要找循环节
由
于
数
是
不
连
续
的
,
先
对
数
排
序
,
找
出
每
个
数
应
该
在
的
位
置
由于数是不连续的,先对数排序,找出每个数应该在的位置
由于数是不连续的,先对数排序,找出每个数应该在的位置
然
后
对
未
访
问
的
数
,
找
对
应
这
个
位
置
应
该
放
的
数
在
哪
然后对未访问的数,找对应这个位置应该放的数在哪
然后对未访问的数,找对应这个位置应该放的数在哪
直
到
再
次
找
到
这
个
循
环
节
的
头
为
止
直到再次找到这个循环节的头为止
直到再次找到这个循环节的头为止
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
bool flag[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;cin>>n;
vector<int> v;
for(int i=1,x;i<=n;i++){
cin>>x;
v.pb(x);
}
map<int,int> m;
vector<int> v1=v;
sort(all(v1));
for(int i=0;i<n;i++)m[v1[i]]=i;
int ans=0;
for(int i=0;i<n;i++){
if(!flag[i]){
int j=i;
while(!flag[j]){
flag[j]=1;
j=m[v[j]];
}
ans++;
}
}
cout<<n-ans;
return 0;
}