这次比赛真的。。。槽点满满啊。。。A,C,D,E都有问题。。。(害我罚时高到飞起)
A.第k小数
读完题,我:这nlogn直接艹,问题不大!
然后。。。
段错误*n
我:???
然后,天真的以为sort出锅了,码了个基排。。。
然后。。。
段错误*n
我:???
之后,自暴自弃,数组开个1e7,于是。。。
答案正确。
我:???
emmm,这题,没啥技巧,sort被卡了,直接上无脑基排吧。。。
注意分正数和负数两个情况讨论
代码:
#include<bits/stdc++.h> using namespace std; const int N=1e7+1; int a[N],d[N],n,k; const int base=256,mod=255; int b[N],c[4][N]; inline int read(){ int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if (ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ x = (x<<1) + (x<<3) + (ch^48); ch = getchar(); } return x * f; } inline void base_sort(){ memset(c,0,sizeof(c)); for(int i=1;i<=n;++i){ c[0][a[i]&mod]++; c[1][(a[i]>>8)&mod]++; c[2][(a[i]>>16)&mod]++; c[3][(a[i]>>24)]++; } for(int i=1;i<=mod;++i){ c[0][i]+=c[0][i-1]; c[1][i]+=c[1][i-1]; c[2][i]+=c[2][i-1]; c[3][i]+=c[3][i-1]; } for(int i=n;i;--i){ b[c[0][a[i]&mod]--]=a[i]; } for(int i=n;i;--i){ a[c[1][(b[i]>>8)&mod]--]=b[i]; } for(int i=n;i;--i){ b[c[2][(a[i]>>16)&mod]--]=a[i]; } for(int i=n;i;--i){ a[c[3][(b[i]>>24)]--]=b[i]; } } int main(){ int T=read(); while(T--){ n=read(),k=read();int e=0,p=0; for(int i=1;i<=n;++i){ int x=read(); if(x<0){ d[++e]=x; }else{ a[++p]=x; } } int reflag=1; if(e>=k){ n=e;reflag=-1; for(int i=1;i<=n;++i){ a[i]=-d[i]; } }else{ n=p; } base_sort(); printf("%d\n",a[k]*reflag); } return 0; }
B.不平行的直线
比较斜率是否一样即可(注意讨论没有斜率的情况)
因为double可能出精度,直接可能炸,于是。。。将分子和分母用pair存起来,然后直接上set就行了。
(为了正确比较,记得化成最简分数,且由于可能为负,我们规定分子必须为非负,就行了)
复杂度:
代码:
#include<bits/stdc++.h> using namespace std; const int N=201; int x[N],y[N]; set<pair<int,int> >sp; int main(){ int n; scanf("%d",&n); int ans=0; for(int i=1;i<=n;++i){ scanf("%d%d",&x[i],&y[i]); } bool flag=0; for(int i=1;i<=n;++i){ for(int j=i+1;j<=n;++j){ if(x[i]==x[j]){ flag=1; continue; } int X=y[i]-y[j],Y=x[i]-x[j]; if(X<0)X=-X,Y=-Y; int D=__gcd(X,Y); X/=D,Y/=D; sp.insert(make_pair(X,Y)); } } int res=sp.size()+flag; printf("%d",res); return 0; }
C.丢手绢
我们枚举每一个点,然后算出离这个点最远的点离这个点的距离就行了。
如果暴力,明显不可行。
观察到可以直接二分/三分。直接上模板即可
复杂度:
代码:
#include<bits/stdc++.h> using namespace std; #define int long long const int N=1e5+1; int s[N],pos[N],n; inline int calc(int x,int y){ if(x>y){ swap(x,y); } return min(abs(pos[x]-pos[y]),pos[x]+s[n]+pos[n]-pos[y]); } signed main(){ scanf("%lld",&n); for(int i=1;i<=n;++i){ scanf("%lld",&s[i]); } scanf("%lld",&s[n]);//这句话看情况加不加吧/xk题面问题 for(int i=2;i<=n;++i){ pos[i]=pos[i-1]+s[i-1]; } int ans=0; for(int i=1;i<=n;++i){ int l=1,r=n,res=0; while(l<=r){ int lc=l+(r-l)/3,rc=r-(r-l)/3; int L=calc(i,lc),R=calc(i,rc); if(L>R){ res=L,r=rc-1; }else{ res=R,l=lc+1; } } ans=max(ans,res); } printf("%lld",ans); return 0; }
D.二分
这题也是诡异。。。
输入描述有这句:
接下来n行,首先是猜的数,然后是一个空格,然后是一个符号。符号如果是“+”说明猜的数比答案大,“-”说明比答案小,“.”说明猜到了答案。
然后,样例解释是:
当目标数组是5时,5 . 5 . 8 - 这三个回答都是正确的
两者明显矛盾了。。。/xk
通过我的多次提交牺牲(qwq),我们发现,输入描述的是正确的,我们按输入描述的做就行了。。。
我们首先,对于每个回答,算出它的可行解的范围。
那么,很明显的,答案就是在最多的可行解范围内的点所包含的可行解范围。(有点绕/xk)
但是,每个可行解的范围其实很大的,我们不可能直接统计,怎么办?
注意到,非端点的数字其实没什么用处(也就是说我们把所有的端点都算一遍就可以求出答案了)
那么,我们直接将所有可行解离散化一遍,然后就是简单的区间加,单点查询问题了,套个数据结构就可以了(ps:建议数组开大点,玄学。。。)
复杂度:
代码:
#include<bits/stdc++.h> using namespace std; const int N=1e6+1; #define int long long struct node{ int l,r; }t[N]; int b[N],s[N],m,e,inf; inline int lowbit(int x){ return x&-x; } inline void insert(int x,int y){ while(x<=e){ s[x]+=y;x+=lowbit(x); } } inline int find(int x){ int ans=0; while(x){ ans+=s[x];x-=lowbit(x); } return ans; } signed main(){ int n; scanf("%lld",&n); e=0,inf=1e17; for(int i=1;i<=n;++i){ int x;char y; cin>>x>>y; if(y=='.'){//x-x ans+1 t[i]=(node){x,x}; }else if(y=='-'){ t[i]=(node){x+1,inf}; }else{ t[i]=(node){-inf,x-1}; } b[++e]=t[i].l,b[++e]=t[i].r; } sort(b+1,b+e+1); m=unique(b+1,b+e+1)-b-1; for(int i=1;i<=n;++i){ t[i].l=lower_bound(b+1,b+m+1,t[i].l)-b; t[i].r=lower_bound(b+1,b+m+1,t[i].r)-b; insert(t[i].l,1),insert(t[i].r+1,-1); } int ans=0; for(int i=1;i<=m;++i){ ans=max(ans,find(i)); } printf("%d",ans); return 0; }
E.交换
一开始以为是交换相邻的,然后光荣贡献了罚时
这道题,直接上结论就行了。
我们把一个点和它排完序后的位置连一条单向边,那么答案就是点的个数-环的个数/每个环的大小-1的和
直接跑暴力一遍就行了,因为每个点都只会被访问一次,所以复杂度是
(看我开的数组就可以猜到我经历了什么qwq)
代码:
#include<bits/stdc++.h> using namespace std; const int N=1000001; int a[N],b[N],nex[N]; bool vis[N]; int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d",&a[i]);b[i]=a[i]; } sort(b+1,b+n+1); int ans=0; for(int i=1;i<=n;++i){ int x=lower_bound(b+1,b+n+1,a[i])-b; nex[i]=x; } for(int i=1;i<=n;++i){ if(nex[i]==i||vis[i])continue; int tot=0,now=i; while(!vis[now]){ ++tot,vis[now]=1;now=nex[now]; } ans+=(tot-1); } printf("%d",ans); return 0; }