21.5.31 t1
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;
}