bzoj5187 [Usaco2018 Jan]Sprinklers(数学+计数+前缀和)
2018-03-13 23:00
465 查看
这题真是神orz
首先我们发现原问题可以转化为:问你有多少对点对(x1,y1),(x2,y2)满足x1<x2,y1<y2x1<x2,y1<y2,每列可以选取的点在一个区间[low,top]中,我们还发现,随着x的递增,每一列的low是单调不增的,top也是单调不增的。(可以反证一下)
我们考虑从左到右枚举x2,每次计算出合法的(x1,y1,y2)三元组的个数加到答案里。合法就需要满足
x1<x2,y1<y2,lowx2<=y2<=topx2,lowx1<=y1<=topx1x1<x2,y1<y2,lowx2<=y2<=topx2,lowx1<=y1<=topx1
我们考虑到如果y2<lowx2y2<lowx2,则y1<y2<lowx2<=lowx1y1<y2<lowx2<=lowx1,(x1,y1)本身就是一个不合法的点,于是我们无需考虑lowx2<=y2这个条件lowx2<=y2这个条件。
我们考虑用所有的满足x1<x2,y1<y2<=topx2x1<x2,y1<y2<=topx2的三元组tot减去其中不合法的三元组,即y1<lowx1y1<lowx1的三元组bad。
我们显然有tot=top∗(top+1)/2∗x2tot=top∗(top+1)/2∗x2
对于bad我们拆开来计算:
对于y1<lowx2y1<lowx2的bad1=x2∗∑lowx2−1y1=0(top−y1)bad1=x2∗∑y1=0lowx2−1(top−y1)
对于lowx2<=y1<=lowx1lowx2<=y1<=lowx1的bad2,我们这样计算:
我们考虑处理出一个数组lst[i],表示不合法的(x1,i)有lft[i]个,即当x1< lft[i]时,(x1,i)均不合法。我们发现对于lowx2<=y1lowx2<=y1,lst[y1]是<=x2的,因此是与x2无关的,于是我们可以预处理出两个前缀和来帮助我们O(1)计算bad2.
总的复杂度就是O(n)O(n)的了。
首先我们发现原问题可以转化为:问你有多少对点对(x1,y1),(x2,y2)满足x1<x2,y1<y2x1<x2,y1<y2,每列可以选取的点在一个区间[low,top]中,我们还发现,随着x的递增,每一列的low是单调不增的,top也是单调不增的。(可以反证一下)
我们考虑从左到右枚举x2,每次计算出合法的(x1,y1,y2)三元组的个数加到答案里。合法就需要满足
x1<x2,y1<y2,lowx2<=y2<=topx2,lowx1<=y1<=topx1x1<x2,y1<y2,lowx2<=y2<=topx2,lowx1<=y1<=topx1
我们考虑到如果y2<lowx2y2<lowx2,则y1<y2<lowx2<=lowx1y1<y2<lowx2<=lowx1,(x1,y1)本身就是一个不合法的点,于是我们无需考虑lowx2<=y2这个条件lowx2<=y2这个条件。
我们考虑用所有的满足x1<x2,y1<y2<=topx2x1<x2,y1<y2<=topx2的三元组tot减去其中不合法的三元组,即y1<lowx1y1<lowx1的三元组bad。
我们显然有tot=top∗(top+1)/2∗x2tot=top∗(top+1)/2∗x2
对于bad我们拆开来计算:
对于y1<lowx2y1<lowx2的bad1=x2∗∑lowx2−1y1=0(top−y1)bad1=x2∗∑y1=0lowx2−1(top−y1)
对于lowx2<=y1<=lowx1lowx2<=y1<=lowx1的bad2,我们这样计算:
我们考虑处理出一个数组lst[i],表示不合法的(x1,i)有lft[i]个,即当x1< lft[i]时,(x1,i)均不合法。我们发现对于lowx2<=y1lowx2<=y1,lst[y1]是<=x2的,因此是与x2无关的,于是我们可以预处理出两个前缀和来帮助我们O(1)计算bad2.
总的复杂度就是O(n)O(n)的了。
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define ll long long #define inf 0x3f3f3f3f #define N 100010 #define mod 1000000007 inline char gc(){ static char buf[1<<16],*S,*T; if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;} return *S++; } inline int read(){ int x=0,f=1;char ch=gc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f; } int n,Y ,lft ,sum ,sum2 ,top ;//Y[i]-->第i列的纵坐标 //lft[i]-->对于x<lft[i],(x,i)不合法,也即不合法的(x1,y1)有lft[y1]个 int main(){ // freopen("a.in","r",stdin); n=read();for(int i=1;i<=n;++i){int x=read();Y[x]=read();} int low=n-1; for(int i=0;i<n;++i) while(Y[i]<=low) lft[low--]=i; while(low>=0) lft[low--]=n; for(int i=n-1;i>=0;--i) sum[i]=(sum[i+1]+lft[i])%mod; for(int i=n-1;i>=0;--i) sum2[i]=(sum2[i+1]+(ll)lft[i]*(n-1-i))%mod; for(int i=n-1;i>=0;--i) top[i]=max(top[i+1],Y[i]); low=n-1;int ans=0; for(int i=1;i<n;++i){ while(low>0&&lft[low-1]<=i) low--; int all=(ll)top[i]*(top[i]+1)/2%mod*i%mod; int bad1=(2LL*top[i]-low+1)*low/2%mod*i%mod; int bad2=sum2[low]-sum2[top[i]+1]-(ll)(sum[low]-sum[top[i]+1])*(n-1-top[i])%mod; bad2%=mod;bad1+=bad2;bad1%=mod;all-=bad1;all%=mod;ans+=all;ans%=mod;if(ans<0) ans+=mod; }printf("%d\n",ans); return 0; }
相关文章推荐
- 【BZOJ】1679: [Usaco2005 Jan]Moo Volume 牛的呼声(数学)
- bzoj5188 [Usaco2018 Jan]MooTube(离线+并查集)
- bzoj5185 [Usaco2018 Jan]Lifeguards(dp+单调队列优化)
- bzoj5189 [Usaco2018 Jan]Cow at Large(树+贪心)
- bzoj5190 [Usaco2018 Jan]Stamp Painting(dp+计数)
- bzoj5193 [Usaco2018 Feb]Cow Gymnasts(数学)
- bzoj 5190: [Usaco2018 Jan]Stamp Painting
- bzoj5186 [Usaco2018 Jan]Cow at Large(树+dfs序+分块+BIT/点分治)
- 【BZOJ1576】[Usaco2009 Jan]安全路经Travel【最短路树】【树链剖分】【线段树】
- BZOJ 1718: [Usaco2006 Jan] Redundant Paths 分离的路径( tarjan )
- bzoj 3050: [Usaco2013 Jan]Seating
- bzoj1634[Usaco2007 Jan]Protecting the Flowers 护花
- BZOJ 3049: [Usaco2013 Jan]Island Travels
- BZOJ [Usaco2007 Jan]Protecting the Flowers 护花(隐藏题)
- BZOJ 2580: [Usaco2012 Jan]Video Game
- 【bzoj1596】[Usaco2008 Jan]电话网络 树形dp
- BZOJ2199: [Usaco2011 Jan]奶牛议会
- BZOJ_1612_[Usaco2008_Jan]_Cow_Contest_奶牛的比赛_(dfs)
- BZOJ 3885 Usaco2015 Jan Cow Rectangles 单调队列+二分
- bzoj1612 [Usaco2008 Jan]Cow Contest奶牛的比赛(Floyd)