您的位置:首页 > 其它

【牛客练习赛11】A B D E

2018-01-27 17:05 381 查看
A 假的线段树

链接:https://www.nowcoder.com/acm/contest/59/A

来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32768K,其他语言65536K

64bit IO Format: %lld

题目描述

给你一个长为n的序列a,有m次操作

1.把区间[l,r]内所有x变成y

2.查询区间[l,r]内第k小值

输入描述:

第一行两个数n,m

第二行n个数表示序列a

后面m行

1 l r x y :把区间[l,r]中所有x变成y

2 l r k :查询区间[l,r]中的第k小值

输出描述:

对于每个询问,输出一个数表示答案

示例1

输入

3 3

2 3 3

2 1 3 1

1 1 3 3 1

2 1 3 2

输出

2

1

备注:

对于100%的数据,1 <= n, m , ai <= 1000

题解: 看数据范围,操作一 暴力没有问题。操作二 ,我们可以用一个容器有序存储所截序列,然后找到第k项就行了。这里要用mutiset ,因为有重复数据。

代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 1e3+11;
int a[MAXN];
multiset<int>S;
multiset<int>::iterator it;
int main() {
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
while(m--){
int l,r,op,x,y;
scanf("%d%d%d%d",&op,&l,&r,&x);
if(op==1){
scanf("%d",&y);
for(int i=l;i<=r;i++){
if(a[i]==x) a[i]=y;
}
}else {
S.clear();
for(int i=l;i<=r;i++){
S.insert(a[i]);
}
int i=1;
for(it=S.begin();it!=S.end();it++,i++){
if(i==x) {
cout<<*(it)<<endl;
break;
}
}
}
}
return 0;
}


B 假的字符串

题解链接

D 求距离

链接:https://www.nowcoder.com/acm/contest/59/D

来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32768K,其他语言65536K

64bit IO Format: %lld

题目描述

给你一个1 -> n的排列,现在有一次机会可以交换两个数的位置,求交换后最小值和最大值之间的最大距离是多少?

输入描述:

第一行一个数n

之后一行n个数表示这个排列

输出描述:

输出一行一个数表示答案

示例1

输入

5

4 5 1 3 2

输出

3

说明

把1和2交换后

序列为4 5 2 3 1

最大值5在数组的2位置,最小值1在数组的5位置

距离为3

备注:

对于100%的数据,1 <= n <= 100

水题

代码

#include<bits/stdc++.h>
using namespace std;
const int inf  = 0x3f3f3f3f;

const int MAXN = 1e3+11;
int arr[MAXN];
struct node{
int pos,num;
}mx,mn;
int main(){
int n;
while(scanf("%d",&n)!=EOF){
mx.num=-1;   mn.num=inf;
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);

if(arr[i]<mn.num){
mn.num=arr[i];
mn.pos=i;
}
if(arr[i]>mx.num){ mx.num=arr[i];mx.pos=i; }
}
int x = max(abs(n-1-mn.pos),abs(mn.pos));
int y = max(abs(n-1-mx.pos),abs(mx.pos));

printf("%d\n",max(x,y));
}
return 0;
}


E 求最值

链接:https://www.nowcoder.com/acm/contest/59/E

来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32768K,其他语言65536K

64bit IO Format: %lld

题目描述

给你一个长为n的序列a

定义f(i,j)=(i-j)2+g(i,j)2

g是这样的一个函数



求最小的f(i,j)的值,i!=j

输入描述:

第一行一个数n

之后一行n个数表示序列a

输出描述:

输出一行一个数表示答案

示例1

输入

4

1 0 0 -1

输出

1

备注:

对于100%的数据,2 <= n <= 100000 , |ai| <= 10000

分析:cf原题,把题目公式变形一下 ,就好看了

f(i,j) = (j-i)^2 + (sum[j] - sum[i] ) ^2

距离公式,所以就是求最近点对问题

代码

#include<bits/stdc++.h>
using namespace std;
#define  LL long long

const int MAXN = 100000 + 10;
const int MAXM = 1e6;
const int mod = 1e9+7;
const LL inf = 0x3f3f3f3f3f3f3f;

struct Node{
LL x,y;
}Point[MAXN],Q[MAXN];
bool cmpx(Node a,Node b) { return a.x<b.x ; }
bool cmpy(Node a,Node b){ return a.y<b.y ; }
LL sqr(LL a) { return a*a;  }
LL GetDis(Node a,Node b){ return sqr(a.x-b.x)+sqr(a.y-b.y); }
LL DIV(int le,int ri){
LL ret=inf;
if(le==ri) return ret;
if(le+1==ri) return GetDis(Point[le],Point[ri]);
int mid=(le+ri)>>1;
LL d1=DIV(le,mid);
LL d2=DIV(mid+1,ri);
ret=min(d1,d2);
double d=sqrt((double)ret);
int k=0;
for(int i=mid;i>=le;i--) {
if(Point[mid].x-Point[i].x>(LL)d) break;
Q[++k]=Point[i];
}
for(int i=mid+1;i<=ri;i++) {
if(Point[i].x-Point[mid].x>(LL)d) break;
Q[++k]=Point[i];
}
sort(Q+1,Q+1+k,cmpy);
for(int i=1;i<k;i++){
for(int j=i+1;j<=k&&Q[j].y-Q[i].y<=(LL)d;j++)
ret=min(ret,GetDis(Q[j],Q[i]));
}
return ret;
}
int a[MAXN];
int main(){
int n;scanf("%d",&n);
LL sum=0;
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
sum+=a[i];
Point[i].x=i;
Point[i].y=sum;
}
sort(Point+1,Point+1+n,cmpx);
printf("%lld\n",DIV(1,n));
return 0;
}


还有就是 可以暴力 我们可以暴力个几千个点 也是可以过的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: