[线段树][单调栈]HackerRank 101 Hack 50 .Boxes for Toys
2017-07-08 21:02
369 查看
传送门
首先可以发现,将三元组排序,一个区间里的maxa∗maxb∗maxc即是这个区间的权值。
考虑枚举右端点r,用线段树维护每个i,i∈[1,r],i到r中maxa∗maxb∗maxc的值,这样用单调栈维护a,b,c,退栈入栈分别用区间除,区间乘更新
首先可以发现,将三元组排序,一个区间里的maxa∗maxb∗maxc即是这个区间的权值。
考虑枚举右端点r,用线段树维护每个i,i∈[1,r],i到r中maxa∗maxb∗maxc的值,这样用单调栈维护a,b,c,退栈入栈分别用区间除,区间乘更新
#include <cstdio> #include <iostream> #include <algorithm> #include <ctime> using namespace std; const int N=300010,P=1e9+7; typedef long long ll; int n; int a ,b ,c ,ia ,ib ,ic ; int prod[N<<2],tag[N<<2]; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void rea(int &x){ char c=nc(); x=0; for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc()); } inline void add(int &x,int y){ (x+=y)%=P; } inline ll Pow(ll x,int y){ ll ret=1; x%=P; for(;y;y>>=1,x=x*x%P) if(y&1) ret=ret*x%P; return ret; } inline void Push(int g){ if(tag[g]!=1){ prod[g<<1]=1LL*prod[g<<1]*tag[g]%P; tag[g<<1]=1LL*tag[g<<1]*tag[g]%P; prod[g<<1|1]=1LL*prod[g<<1|1]*tag[g]%P; tag[g<<1|1]=1LL*tag[g<<1|1]*tag[g]%P; tag[g]=1; } } inline void Up(int g){ prod[g]=(prod[g<<1]+prod[g<<1|1])%P; } void Build(int g,int l,int r){ tag[g]=1; if(l==r) return prod[g]=1,void(); int mid=l+r>>1; Build(g<<1,l,mid); Build(g<<1|1,mid+1,r); Up(g); } void Modify(int g,int l,int r,int L,int R,int x){ if(l==L&&r==R){ tag[g]=1LL*tag[g]*x%P; prod[g]=1LL*prod[g]*x%P; return ; } Push(g); int mid=L+R>>1; if(r<=mid) Modify(g<<1,l,r,L,mid,x); else if(l>mid) Modify(g<<1|1,l,r,mid+1,R,x); else Modify(g<<1,l,mid,L,mid,x),Modify(g<<1|1,mid+1,r,mid+1,R,x); Up(g); } int Query(int g,int l,int r,int L,int R){ if(l==L&&r==R) return prod[g]; Push(g); int mid=L+R>>1; if(r<=mid) return Query(g<<1,l,r,L,mid); if(l>mid) return Query(g<<1|1,l,r,mid+1,R); return (Query(g<<1,l,mid,L,mid)+Query(g<<1|1,mid+1,r,mid+1,R))%P; } int stka ,stkb ,stkc ,tpa,tpb,tpc; int main(){ freopen("box.in","r",stdin); freopen("box.out","w",stdout); rea(n); for(int i=1;i<=n;i++){ rea(a[i]); rea(b[i]); rea(c[i]); if(b[i]>a[i]) swap(a[i],b[i]); if(c[i]>a[i]) swap(a[i],c[i]); if(c[i]>b[i]) swap(b[i],c[i]); ia[i]=Pow(a[i],P-2); ib[i]=Pow(b[i],P-2); ic[i]=Pow(c[i],P-2); } Build(1,1,n); int ans=0; for(int i=1;i<=n;i++){ while(tpa && a[i]>a[stka[tpa]]) Modify(1,stka[tpa-1]+1,stka[tpa],1,n,ia[stka[tpa]]),tpa--; Modify(1,stka[tpa]+1,i,1,n,a[i]); stka[++tpa]=i; while(tpb && b[i]>b[stkb[tpb]]) Modify(1,stkb[tpb-1]+1,stkb[tpb],1,n,ib[stkb[tpb]]),tpb--; Modify(1,stkb[tpb]+1,i,1,n,b[i]); stkb[++tpb]=i; while(tpc && c[i]>c[stkc[tpc]]) Modify(1,stkc[tpc-1]+1,stkc[tpc],1,n,ic[stkc[tpc]]),tpc--; Modify(1,stkc[tpc]+1,i,1,n,c[i]); stkc[++tpc]=i; add(ans,Query(1,1,i,1,n)); } ans=1LL*ans*Pow(1LL*(n+1)*n/2,P-2)%P; printf("%d\n",ans); return 0; }
相关文章推荐
- [线段树 || 主席树][Hash] HackerRank 101 Hack 49. Sorting Lists
- [HackerRank 101 Hack 51] Train Trip
- Hackerrank 101 Hack 42 Array Pairs
- [HackerRank 101 Hack 51] Small Cubes
- [Hackerrank 101 Hack 43&& MenciOJ P321] K-Inversion Permutations
- [HackerRank 101 Hack 42]Array Pairs
- [HackerRank 101 Hack 51] Testing the Game
- Hackerrank Medium(50) Permutation Happiness 递推
- Hackerrank - Similar Pair 与线段树解法
- [Hackerrank题目选做] Sorted Subsegments 二分+线段树
- HackerRank - Insertion Sort Advanced Analysis
- 【Hacker Rank】04.Arithmetic Operators
- Hackerrank How many substrings
- hackerrank_Permutation game
- 线段树和单调队列优化DP---POJ2373解题报告
- hackerrank-2D Array - DS
- *[hackerrank]Jim Beam
- STVD弹出"Line number 50 is out of range for "main.c"."的原因及解决办法
- [JSOI2008] [洛谷P1198] 最大数|线段树80'|单调栈100'
- vi 打开大文件报错:(0602-101 Out of memory saving lines for undo)