三步必殺
阿新 • • 發佈:2018-10-05
tps 說過 turn %d 相反數 數組 main include 一點
傳送門
這是一道非常優秀的差分題。聽說過二階差分維護嗎?
我們在區間加的時候是可以用差分維護的,不過這次我們要往裏面加一個等差數列,這個維護起來就稍微麻煩了一點。
我的想法比較復雜,就是先用第一階差分去維護公差,在l+1和r的位置進行修改,前者加公差後者減公差。然後我們同時要記錄首項和末項相反數,然後在每次修改l的位置加上首項,在r+1的位置加上末項相反數,再跑一遍差分,就得到最後的數組啦。
最後異或+比大小即可。
完美的O(n)。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<queue> #include<cstring> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar(‘\n‘) #define pr pair<int,int> #define mp make_pair #define fi first #define sc second using namespace std; typedef long long ll; const intM = 300005; const int N = 10000005; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < ‘0‘ || ch > ‘9‘) { if(ch == ‘-‘) op = -1; ch = getchar(); } while(ch >=‘0‘ && ch <= ‘9‘) { ans *= 10; ans += ch - ‘0‘; ch = getchar(); }return ans * op; } ll n,m,l,r,s,e,c[N],p[M],ans,maxn,v[M],d,q[M],g[M]; int main() { n = read(),m = read(); rep(i,1,m) { l = read(),r = read(),s = read(),e = read(); d = (e-s) / (r-l); c[l+1] += d,c[r+1] -= d; q[i] = l,g[i] = s,p[i] = r+1,v[i] = -e; } rep(i,1,n) c[i] += c[i-1]; //rep(i,1,n) printf("%d ",c[i]);enter; rep(i,1,m) c[q[i]] += g[i],c[p[i]] += v[i]; //rep(i,1,n) printf("%d ",c[i]);enter; rep(i,1,n) c[i] += c[i-1]; //rep(i,1,n) printf("%d ",c[i]);enter; rep(i,1,n) ans ^= c[i],maxn = max(maxn,c[i]); printf("%lld %lld\n",ans,maxn); return 0; }
三步必殺