数列操作(差分)问题
给定一个长度为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 }