数列操作(差分)问题

给定一个长度为n的数列{a1,a2...an},每次可以选择一个区间[l,r],使这个区间内的数都加一或者都减一。
问至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列有多少种。

 

差分的应用,先把数组变成前缀和的形式:

如:4 5 6 4 换成 4 1 1 -2

然后就会发现区间增减操作实际上变成了区间端点的增减操作;

然后就可以用贪心方法过掉;wa了好几次,都是没搞清楚负数的影响;

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cstdlib>
 6 #include<algorithm>
 7 #include<ctime>
 8 #include<cmath>
 9 #include<queue>
10 #include<map>
11 #include<set>
12 using namespace std;
13 #define FILE "dealing"
14 #define LL long long
15 #define up(i,j,n) for(int i=j;i<=n;i++)
16 #define pii pair< int , int >
17 #define abs(x) (x)<0?-(x):(x)
18 namespace IO{
19     char buf[1<<15],*fs,*ft;
20     int gc(){return fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft),fs==ft?-1:*fs++;}
21     LL read(){
22         LL x=0,ch=gc(),f=0;
23         while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();}
24         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();}
25         return f?-x:x;
26     }
27 }using namespace IO;
28 const int maxn(100500);
29 int n;
30 LL a[maxn],sum[maxn],c[maxn];
31 int main(){
32     freopen(FILE".in","r",stdin);
33     freopen(FILE".out","w",stdout);
34     n=read();
35     up(i,1,n)a[i]=read();
36     up(i,1,n)c[i]=a[i]-a[i-1];
37     LL x=0,y=0;
38     for(int i=2;i<=n;i++){
39         if(c[i]>0)x+=c[i];
40         else y-=c[i];
41     }
42     printf("%I64d\n",max(x,y));
43     printf("%I64d\n",max(x,y)-min(x,y)+1);
44     return 0;
45 }
View Code

 

posted @ 2016-11-15 16:54  CHADLZX  阅读(391)  评论(0编辑  收藏  举报