题目链接:http://poj.org/problem?id=2566
题意:给定一个序列(n个整数)和一个整数k(m个),求出这个序列的一个子串,使之和的绝对值与k的差最小。
尺取法的题目有两个特性:
1. 所求的序列是一个连续的序列,这样才能将序列抽象成一个头和一个尾来描述。
2. 头尾枚举的序列满足某种单调的性质,这样才能进行尺取的操作。
这个序列是一个随意的序列,不可能直接对其进行操作,先要预处理下,进行前缀和操作,把对应的值和标记放在同一个pair。
然后根据前缀和的值进行排序,这样就符合尺取法的两个特性了。
其他的就是一些细节上的东西了。直接上代码,(•‾??‾?•)??°,
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 const int INF=0x3f3f3f3f; 6 const int N=100011; 7 pair <int,int> T[N]; 8 9 //前缀和初始化 10 void init(int n){ 11 T[0]=make_pair(0,0);//这里需要放一个0,0进去,不然有一些值就取不到了. 12 int x,tmp=0; 13 for(int i=1;i<=n;i++){ 14 scanf("%d",&x); 15 tmp+=x; 16 T[i]=make_pair(tmp,i); 17 } 18 sort(T,T+n+1); 19 } 20 21 int main(){ 22 int n,m; 23 while(scanf("%d %d",&n,&m)){ 24 if(n==0&&m==0) break; 25 init(n); 26 for(int i=1;i<=m;i++){ 27 int l=0,r=1,t=INF; 28 int tmp,ansl,ansr,ans; 29 scanf("%d",&tmp); 30 while(r<=n&&t){ 31 int temp=T[r].first-T[l].first; 32 if(abs(temp-tmp)<t){ 33 t=abs(temp-tmp); 34 ans=temp; 35 ansl=T[l].second; 36 ansr=T[r].second; 37 } 38 if(temp<tmp) r++; 39 if(temp>tmp) l++; 40 if(temp==tmp) break; 41 if(l==r) r++; //保证r>=l 42 } 43 if(ansl>ansr) swap(ansl,ansr);//因为是经过排序过的,有可能左边的比右边的大. 44 printf("%d %d %d\n",ans,ansl+1,ansr);//左边多加了一个0,需要+1 45 } 46 } 47 return 0; 48 }
时间: 2024-11-05 19:49:58