VP*n

给出若干个点的坐标,求经过所有点所需要最短距离。
思路:找四个方向上最外侧的点,其实最终的距离一定是最外侧点组成的矩形的周长,具体可以看样例给的图片。注意最小值是与0的距离,因为存在在x轴上和y轴上的点。
AC Code:
- #include
-
- typedef long long ll;
- const int N=105;
- int t,n;
-
- int main(){
- std::ios::sync_with_stdio(false);
- std::cin.tie(0);
- std::cout.tie(0);
- std::cin>>t;
- while(t--){
- std::cin>>n;
- int minx=0,miny=0,maxx=0,maxy=0;
- for(int i=1;i<=n;i++){
- int x,y;
- std::cin>>x>>y;
- if(y==0){
- if(x>0) maxx=std::max(maxx,x);
- else minx=std::min(minx,x);
- }
- else{
- if(y>0) maxy=std::max(maxy,y);
- else miny=std::min(miny,y);
- }
- }
- std::cout<<2*(maxx-minx)+2*(maxy-miny)<<'\n';
- }
- return 0;
- }

对于一个数组,它的值是通过以下操作得到全0数组的操作数:选择一个连续区间,将其中的每个数-1。对于给出的数组,若存在一个新的排列顺序使得它的值小于原数组,输出no,否则输出yes。
思路:使得较大数不能减少操作次数的原因是有较小数截断。所以只要存在一个数两侧都有大于它的数,那一定存在更少的操作次数。
AC Code:
- #include
-
- typedef long long ll;
- const int N=1e5+5;
- int t,n;
- int a[N],left[N],right[N];
-
- int main(){
- std::ios::sync_with_stdio(false);
- std::cin.tie(0);
- std::cout.tie(0);
- std::cin>>t;
- while(t--){
- std::cin>>n;
- for(int i=1;i<=n;i++){
- std::cin>>a[i];
- }
- memset(left,0,sizeof(left));
- memset(right,0,sizeof(right));
- for(int i=1;i<=n;i++){
- left[i]=std::max(left[i-1],a[i]);
- }
- for(int i=n;i>=1;i--){
- right[i]=std::max(right[i+1],a[i]);
- }
- bool flag=true;
- for(int i=2;i
- if(left[i]>a[i]&&right[i]>a[i]){
- flag=false;
- break;
- }
- }
- std::cout<<(flag?"YES":"NO")<<'\n';
- }
- return 0;
- }
C. Build Permutation

给出0到n-1,以及相同的下标,构造一个数组,使得元素和下标之和是完全平方数。
思路:举个例子先:
- 7
- 1 0 2 6 5 4 3
这样后一半都是9,前一半是n==3的子问题。观察元素排列情况,其实是有这样的规律:存在一个区间[l,r],这个区间内原始数字(指初始情况为a[i]=i)倒转后与下标的和一定是完全平方数。这样就很容易了,从较大数开始找这个可以满足条件的完全平方数,依次向前构造即可。
AC Code:
- #include
-
- typedef long long ll;
- const int N=1e5+5;
- int t,n;
- int a[N],left[N],right[N];
-
- int main(){
- std::ios::sync_with_stdio(false);
- std::cin.tie(0);
- std::cout.tie(0);
- std::cin>>t;
- while(t--){
- std::cin>>n;
- std::vector<int>a(n+1,0);
- int now=n,w=n;
- while(n){
- int t=sqrt(n);
- while(!(n-1<=t*t&&t*t<=2*(n-1))) t++;
- int u=t*t-(n-1);
- int len=n-u;
- for(int i=1;i<=len;i++){
- a[now]=t*t-now+1;
- now--;
- }
- n-=len;
- }
- for(int i=1;i<=w;i++){
- std::cout<" \n"[i==w];
- }
- }
- return 0;
- }
D. Tournament Countdown

根据序号排列,相邻两者比赛决胜负,胜者留下,败者删去,最多询问这么多次两个人的胜负情况,输出最后胜利者的编号。
思路:看一种情况,即仅有4个人的时候,一定最后结果是0,0,1,2,0和0是第一局失败的人,2是这四个人中胜利者,保留它,这样可以以4为一组,不断重复这个操作,这样我们每次询问都可以使剩余人数成为原来的四分之一,这样计算询问次数可以这样:

满足给出的条件。
AC Code:
- #include
-
- typedef long long ll;
- const int N=1e5+5;
- int t,n;
- int a[N],left[N],right[N];
-
- int ask(int a,int b){
- std::cout<<"? "<' '<
- int x;
- std::cin>>x;
- return x;
- }
-
- int main(){
- std::ios::sync_with_stdio(false);
- std::cin.tie(0);
- std::cout.tie(0);
- std::cin>>t;
- while(t--){
- std::cin>>n;
- int m=1<
- std::vector<int>a;
- for(int i=1;i<=1<
- a.push_back(i);
- }
- while(m>=4){
- std::vector<int>b;
- for(int i=0;i
4){ - int t1=ask(a[i],a[i+2]);
- if(t1==0){
- int t2=ask(a[i+1],a[i+3]);
- if(t2==1) b.push_back(a[i+1]);
- else b.push_back(a[i+3]);
- }
- else if(t1==1){
- int t2=ask(a[i],a[i+3]);
- if(t2==1) b.push_back(a[i]);
- else b.push_back(a[i+3]);
- }
- else{
- int t2=ask(a[i+1],a[i+2]);
- if(t2==1) b.push_back(a[i+1]);
- else b.push_back(a[i+2]);
- }
- }
- a.swap(b);
- m/=4;
- }
- else{
-
-
相关阅读:
MQ系列14:MQ如何做到消息延时处理
如何系统地去学python
栈OJ(C++)
用acme.sh给网站域名,申请免费SSL永久证书(自动续期)
SoundTouch对音频处理(Android)
中级java面试问题大全及答案大全
PDF标准详解(一)——PDF文档结构
代码审计——任意文件下载详解(二)
向毕业妥协系列之机器学习笔记:构建ML系统(四)
【Redis 开发】缓存穿透解决
-
原文地址:https://blog.csdn.net/m0_62289613/article/details/126492555