101775J(2017 EC final)
阿新 • • 發佈:2018-12-11
題目連結:點選這裡
解題思路:
差分序列:b[i] = a[i] - a[i-1]
原序列為: 1 4 5 8 7 差分後: 1 3 1 3 -1 -7,多出來的以為可以看做0 - a[n].
差分序列的性質:前i項和等於原序列的a[i],這個很容易就能證明
如果要對一個區間的數都加上1,那麼就是a[l]++,a[r+1]--,之後求一下字首和就是當前位置更新後的值了.
那不是和差分序列的性質一樣嗎?
對於本題來說任意大於3的長度都能分解為若干個3-5的段,那麼在差分序列中值是負的說明他執行了更多的a[r+1]--,反之正的亦然.
對於負的考慮之前有沒有那麼的更新此時使得i這位置可以變成該負值,如果不能就是No
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int mx = 2e5 + 10; int n,m,a[mx],b[mx]; int main() { int t,ca = 1; scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",a+i); b[0] = a[0]; a[n] = 0; for(int i=1;i<=n;i++) b[i] = a[i] - a[i-1]; int flag = 1; if(b[1]<0||b[2]<0) flag = 0; else{ ll sum = 0; for(int i=0;i<=n;i++){ if(b[i]>0) sum += b[i]; int p = i + 3;//大於三的長度可以任意分解成若干個3-5的段 if(p>n) break; if(b[p]<0) sum += b[p]; if(sum<0) break;//如果是負的,說明b[p]沒有被清除掉,之後也不會被清除掉,所以No } if(sum) flag = 0; } printf("Case #%d: %s\n",ca++,flag?"Yes":"No"); } return 0; }