题解 P4184【[USACO18JAN]Sprinklers P】
P4184 [USACO18JAN]Sprinklers P解题报告:
更好的阅读体验
第
题意
有一个
分析
题解里差分写法看不懂,来一发比较套路的dp优化吧。
首先不难发现能选用的格点会形成一个类似这样的图形:
.xxx.
.xxx.
.xxx.
xxxx.
xxxx.
每一行能选用的格点是连续的,且左端点,右端点随着行数的增加而不断左移。
那么就很容易预处理:
然后就可以列出式子(
那么剩下的工作就很显然了,这个式子可以优化到
设
利用关键点的坐标为
代码
注意题目中关键点的坐标是从
#include<stdio.h>
const int maxn=100005,mod=1000000007;
int n,pos,ans;
int l[maxn],r[maxn],up[maxn],y[maxn],sum1[maxn],sum2[maxn];
inline int min(int a,int b){
return a<b? a:b;
}
inline int max(int a,int b){
return a>b? a:b;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int a,b;
scanf("%d%d",&a,&b);
a++,b++,y[a]=b;
}
l[0]=n;
for(int i=1;i<=n;i++)
l[i]=min(l[i-1],y[i]);
r[n+1]=0;
for(int i=n;i>=1;i--)
r[i]=max(r[i+1],y[i]);
pos=r[1];
for(int i=1;i<=n;i++)
while(pos>=1&&pos>=l[i])
up[pos]=i,pos--;
for(int i=1;i<=n;i++)
sum1[i]=(sum1[i-1]+up[i])%mod;
for(int i=1;i<=n;i++)
sum2[i]=(sum2[i-1]+1ll*i*up[i]%mod)%mod;
for(int i=1;i<=n;i++)
ans=(ans+1ll*i*(1ll*(r[i]-l[i])*(r[i]-l[i]+1)/2ll%mod)%mod-1ll*(sum1[r[i]-1]-sum1[l[i]-1]+mod)%mod*r[i]%mod+(sum2[r[i]-1]-sum2[l[i]-1]+mod)%mod)%mod;
printf("%d\n",(ans+mod)%mod);
return 0;
}