比赛链接:https://ac.nowcoder.com/acm/contest/5773
A.第k小数
题意
求第k小数
题解
这道题有点毒,sort会被卡掉,其实只要把前k个小的数排出来就行了,所以用nth_element(a,a+k-1,a+n);意思就是只把第k个小的数放在k的位置,第 k个元素之前的元素都小于它,但不必是有序的。同样,第 k个元素后的元素都大于它,但也不必是有序的。
代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define lowbit(x) x&(-x)
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll, ll> pll;
const int N = 5e6+5;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps =1e-9;
const double PI=acos(-1.0);
const int dir[4][2]={-1,0,1,0,0,-1,0,1};
const int exdir[4][2]={1,1,1,-1,-1,1,-1,-1};
ll qpow(ll x,ll y){
ll ans=1,t=x;
while(y>0){
if(y&1)ans*=t,ans%=mod;
t*=t,t%=mod;
y>>=1;
}
return ans%mod;
}
int a[N];
void solve(){
int n,k;cin>>n>>k;
for(int i=0;i<n;i++)cin>>a[i];
nth_element(a,a+k-1,a+n);
cout<<a[k-1];
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--)solve(),cout<<'\n';
//solve();
return 0;
}
B不平行的直线
题意
给一些不重合的点,可以两两成直线,问最多选多少两两相交的直线
题解
找斜率不同的直线个数即可,注意垂直x轴情况
代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define lowbit(x) x&(-x)
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll, ll> pll;
const int N = 1e5+5;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps =1e-9;
const double PI=acos(-1.0);
const int dir[4][2]={-1,0,1,0,0,-1,0,1};
const int exdir[4][2]={1,1,1,-1,-1,1,-1,-1};
ll qpow(ll x,ll y){
ll ans=1,t=x;
while(y>0){
if(y&1)ans*=t,ans%=mod;
t*=t,t%=mod;
y>>=1;
}
return ans%mod;
}
int x[201],y[201];
void solve(){
int n;cin>>n;
set<double>s;
for(int i=0;i<n;i++)cin>>x[i]>>y[i];
int f=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(x[i]==x[j])f=1;
else{
s.insert(1.0*(y[i]-y[j])/(x[i]-x[j]));
}
}
}
cout<<s.size()+f;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
//int t;cin>>t;
//while(t--)solve(),cout<<'\n';
solve();
return 0;
}
C.丢手绢
题意
给你一些点,围成一个圈,每两相邻个点有距离,求两个点之间的最大距离,距离定义为圆的弧长
题解
选一个参考点,求所有点到这点的距离,通过相差就可以求出任意两点的距离,然后枚举每一个点,求这点到其他点最大距离,我们发现这是一个凸函数,直接三分即可
代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define lowbit(x) x&(-x)
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll, ll> pll;
const int N = 1e5+5;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps =1e-9;
const double PI=acos(-1.0);
const int dir[4][2]={-1,0,1,0,0,-1,0,1};
const int exdir[4][2]={1,1,1,-1,-1,1,-1,-1};
ll qpow(ll x,ll y){
ll ans=1,t=x;
while(y>0){
if(y&1)ans*=t,ans%=mod;
t*=t,t%=mod;
y>>=1;
}
return ans%mod;
}
int sum[N],a[N];
int judge(int x,int y){
if(x==y)return 0;
//cout<<x<<' '<<y<<' '<<min(abs(sum[x]-sum[y]),a[1]-abs(sum[x]-sum[y]))<<endl;
return min(abs(sum[x]-sum[y]),a[1]-abs(sum[x]-sum[y]));
}
void solve(){
int n;cin>>n;
for(int i=2;i<=n;i++)cin>>a[i],sum[i]+=sum[i-1]+a[i];
cin>>a[1];a[1]+=sum[n];
int ans=0;
for(int i=1;i<=n;i++){
int l=0,r=n+1;
while(l+1<r){
int lm=(l+r)>>1,rm=(lm+r)>>1;
if(judge(lm,i)>judge(rm,i))r=rm;
else l=lm;
}
ans=max(ans,judge(l,i));
}
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
//int t;cin>>t;
//while(t--)solve(),cout<<'\n';
solve();
return 0;
}
D.二分
题意
不好描述
题解
差分裸题,三种情况讨论
if(s=="+")m[x]--,now++;//负无穷到x-1,全部加一 if(s=="-")m[x+1]++;//x+1到正无穷全部加一 if(s==".")m[x]++,m[x+1]--;//x加一
统计时算一下前缀和就好了
可以离散化一下,亦可以直接map记录
代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define lowbit(x) x&(-x)
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll, ll> pll;
const int N = 1e5+5;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps =1e-9;
const double PI=acos(-1.0);
const int dir[4][2]={-1,0,1,0,0,-1,0,1};
const int exdir[4][2]={1,1,1,-1,-1,1,-1,-1};
ll qpow(ll x,ll y){
ll ans=1,t=x;
while(y>0){
if(y&1)ans*=t,ans%=mod;
t*=t,t%=mod;
y>>=1;
}
return ans%mod;
}
void solve(){
map<int,int>m;
int n;cin>>n;
int now=0;
for(int i=0;i<n;i++){
int x;string s;cin>>x>>s;
if(s=="+")m[x]--,now++;
if(s=="-")m[x+1]++;
if(s==".")m[x]++,m[x+1]--;
}
int ans=0;
for(auto i:m){
now+=i.se;
ans=max(ans,now);
}
cout<<ans;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
//int t;cin>>t;
//while(t--)solve(),cout<<'\n';
solve();
return 0;
}
E.交换
题意
给你一个个数列,问最少交换几次才能使其从大到小有序
题解
第一反应可能是逆序对,或者最长上升子序列之类的,但是这个要求可以任意换,可以不相邻,比如说312,可以3-2,2-1,其实在2-1时成了一个环,每出现一个环答案就会减一,所以找环的个数
代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define lowbit(x) x&(-x)
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll, ll> pll;
const int N = 1e5+5;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps =1e-9;
const double PI=acos(-1.0);
const int dir[4][2]={-1,0,1,0,0,-1,0,1};
const int exdir[4][2]={1,1,1,-1,-1,1,-1,-1};
ll qpow(ll x,ll y){
ll ans=1,t=x;
while(y>0){
if(y&1)ans*=t,ans%=mod;
t*=t,t%=mod;
y>>=1;
}
return ans%mod;
}
int a[N],b[N],v[N];
void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],b[i]=a[i];
sort(a+1,a+1+n);
int now=0;
for(int i=1;i<=n;i++){
if(!v[i]){
int k=lower_bound(a+1,a+1+n,b[i])-a;
v[i]=1;
while(!v[k]){
v[k]=1;
k=lower_bound(a+1,a+1+n,b[k])-a;
}
now++;
}
}
cout<<n-now;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
//int t;cin>>t;
//while(t--)solve(),cout<<'\n';
solve();
return 0;
}



京公网安备 11010502036488号