1. 程式人生 > >三步必殺

三步必殺

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 int
M = 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; }

三步必殺