21.5.31 t1
阿新 • • 發佈:2021-06-25
tag:線段樹,貪心
根據貪心不難想到,每個物品都從大到小排序,然後一個區間的答案就是3個值的區間max乘起來。
所以要求的就是
\[\sum_{l\le r}max_a[l,r]\cdot max_b[l,r]\cdot max_c[l,r] \]一個常見的套路,列舉右端點,線段樹維護答案,用一個單調棧維護max的變化。
維護的時候要支援區間覆蓋a/b/c,所以把 \(\sum a,b,c,ab,bc,ca,abc\) 全部記下來即可。
大常數 \(O(nlogn)\),\(2e5\) 本地 \(1.1s\)
#include<bits/stdc++.h> using namespace std; template<typename T> inline void Read(T &n){ char ch; bool flag=false; while(!isdigit(ch=getchar()))if(ch=='-')flag=true; for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48)); if(flag)n=-n; } enum{ MAXN = 200005, MOD = 1000000007 }; inline int ksm(int base, int k=MOD-2){ int res=1; while(k){ if(k&1) res = 1ll*res*base%MOD; base = 1ll*base*base%MOD; k >>= 1; } return res; } inline int dec(int a, int b){ // assert(0<=a and a<MOD and 0<=b and b<MOD); a -= b; if(a<0) a += MOD; return a; } inline int inc(int a, int b){ // assert(0<=a and a<MOD and 0<=b and b<MOD); a += b; if(a>=MOD) a -= MOD; return a; } inline void ddec(int &a, int b){a = dec(a,b);} inline void iinc(int &a, int b){a = inc(a,b);} inline void upd(int &a, long long b){a = (a+b)%MOD;} int n; int a[3][MAXN], q[3][MAXN], top[3], ans; struct node{ int s1, s2, s3, s12, s23, s13, s123, fil1, fil2, fil3, sz; #define s1(x) t[x].s1 #define s2(x) t[x].s2 #define s3(x) t[x].s3 #define s12(x) t[x].s12 #define s23(x) t[x].s23 #define s13(x) t[x].s13 #define s123(x) t[x].s123 #define fil1(x) t[x].fil1 #define fil2(x) t[x].fil2 #define fil3(x) t[x].fil3 #define sz(x) t[x].sz }t[MAXN<<2]; inline int lc(int x){return x<<1;} inline int rc(int x){return x<<1|1;} inline void Push_Up(int x){ s1(x) = inc(s1(lc(x)),s1(rc(x))); s2(x) = inc(s2(lc(x)),s2(rc(x))); s3(x) = inc(s3(lc(x)),s3(rc(x))); s12(x) = inc(s12(lc(x)),s12(rc(x))); s23(x) = inc(s23(lc(x)),s23(rc(x))); s13(x) = inc(s13(lc(x)),s13(rc(x))); s123(x) = inc(s123(lc(x)),s123(rc(x))); } inline void Fill1(int x, int fil1){ fil1(x) = fil1; s1(x) = 1ll*sz(x)*fil1%MOD; s12(x) = 1ll*s2(x)*fil1%MOD; s13(x) = 1ll*s3(x)*fil1%MOD; s123(x) = 1ll*s23(x)*fil1%MOD; } inline void Fill2(int x, int fil2){ fil2(x) = fil2; s2(x) = 1ll*sz(x)*fil2%MOD; s12(x) = 1ll*s1(x)*fil2%MOD; s23(x) = 1ll*s3(x)*fil2%MOD; s123(x) = 1ll*s13(x)*fil2%MOD; } inline void Fill3(int x, int fil3){ fil3(x) = fil3; s3(x) = 1ll*sz(x)*fil3%MOD; s13(x) = 1ll*s1(x)*fil3%MOD; s23(x) = 1ll*s2(x)*fil3%MOD; s123(x) = 1ll*s12(x)*fil3%MOD; } inline void Push_Down(int x){ if(~fil1(x)) Fill1(lc(x),fil1(x)), Fill1(rc(x),fil1(x)), fil1(x) = -1; if(~fil2(x)) Fill2(lc(x),fil2(x)), Fill2(rc(x),fil2(x)), fil2(x) = -1; if(~fil3(x)) Fill3(lc(x),fil3(x)), Fill3(rc(x),fil3(x)), fil3(x) = -1; } void Build(int x, int head, int tail){ sz(x) = tail-head+1; fil1(x) = fil2(x) = fil3(x) = -1; if(head==tail) return; int mid = head+tail >> 1; Build(lc(x),head,mid); Build(rc(x),mid+1,tail); } void Fill1(int x, int head, int tail, int l, int r, int fil1){ if(l<=head and tail<=r) return Fill1(x,fil1); Push_Down(x); int mid = head+tail >> 1; if(l<=mid) Fill1(lc(x),head,mid,l,r,fil1); if(mid<r) Fill1(rc(x),mid+1,tail,l,r,fil1); Push_Up(x); } void Fill2(int x, int head, int tail, int l, int r, int fil2){ if(l<=head and tail<=r) return Fill2(x,fil2); Push_Down(x); int mid = head+tail >> 1; if(l<=mid) Fill2(lc(x),head,mid,l,r,fil2); if(mid<r) Fill2(rc(x),mid+1,tail,l,r,fil2); Push_Up(x); } void Fill3(int x, int head, int tail, int l, int r, int fil3){ if(l<=head and tail<=r) return Fill3(x,fil3); Push_Down(x); int mid = head+tail >> 1; if(l<=mid) Fill3(lc(x),head,mid,l,r,fil3); if(mid<r) Fill3(rc(x),mid+1,tail,l,r,fil3); Push_Up(x); } void check(int x=1, int head=1, int tail=n){ if(head==tail){printf("%d %d %d\n",s1(x),s2(x),s3(x));return;} Push_Down(x); int mid = head+tail >> 1; check(lc(x),head,mid); check(rc(x),mid+1,tail); } inline int tp(int id){return q[id][top[id]];} int main(){ // freopen("1.in","r",stdin); // freopen("11.out","w",stdout); Read(n); Build(1,1,n); for(int i=1; i<=n; i++){ for(int j=0; j<3; j++) Read(a[j][i]); for(int j=0; j<3; j++) for(int k=j+1; k<3; k++) if(a[j][i]<a[k][i]) swap(a[j][i],a[k][i]); } // for(int i=1; i<=n; i++,puts("")) for(int j=0; j<3; j++) printf("%d ",a[j][i]);puts(""); for(int i=1; i<=n; i++){ for(int j=0; j<3; j++) while(top[j] and a[j][tp(j)]<a[j][i]) top[j]--; Fill1(1,1,n,tp(0)+1,i,a[0][i]); Fill2(1,1,n,tp(1)+1,i,a[1][i]); Fill3(1,1,n,tp(2)+1,i,a[2][i]); for(int j=0; j<3; j++) q[j][++top[j]] = i; iinc(ans,s123(1)); // check();puts(""); } cout<<1ll*ksm(1ll*n*(n+1)/2%MOD)*ans%MOD<<'\n'; return 0; }