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;
}
还有就是 可以暴力 我们可以暴力个几千个点 也是可以过的。