P10196 [USACO24FEB] Lazy Cow P
数据结构题
考虑到
因为贡献是
定每天准备
区间赋值,区间和查询,最长值相等区间长度,即可用线段树维护,以下是一份丑陋的代码。
#include<stdio.h>
const int N=200005;
const int M=4000005;
const int K=1000000;
#define ll long long
const ll P=1000000007;
inline ll Q(ll x,ll y=P-2,ll z=1){
for(;y;y>>=1,x=x*x%P)
(y&1)&&(z=z*x%P);return z;
}
bool t[M];
int lb[M],rb[M];
ll lf[M],rf[M];
ll sm[M],lz[M];
#define ls (x<<1)
#define rs (x<<1|1)
inline void tag(int x,int l,int r,ll v){
sm[x]=(r-l+1)*v;
lb[x]=rb[x]=r-l+1;
lf[x]=rf[x]=v;
lz[x]=v;
}
inline void pushdown(int x,int l,int r){
if(lz[x]>=0){
int mid=(l+r)>>1;
tag(ls,l,mid,lz[x]);
tag(rs,mid+1,r,lz[x]);
lz[x]=-1;
}
}
inline void pushup(int x,int l,int r){
sm[x]=sm[ls]+sm[rs];
lf[x]=lf[ls];
rf[x]=rf[rs];
lb[x]=(t[ls]&&rf[ls]==lf[rs])?(lb[ls]+lb[rs]):lb[ls];
rb[x]=(t[rs]&&rf[ls]==lf[rs])?(rb[rs]+rb[ls]):rb[rs];
t[x]=(lb[x]==r-l+1);
}
void build(int x,int l,int r){
sm[x]=0;
lz[x]=-1;
lb[x]=rb[x]=r-l+1;
lf[x]=rf[x]=0;
t[x]=1;
if(l<r){
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
}
}
void update(int x,int l,int r,int L,int R,ll v){
if(L>R||r<L||l>R) return ;
if(L<=l&&r<=R){
tag(x,l,r,v);
return ;
}
int mid=(l+r)>>1;
pushdown(x,l,r);
update(ls,l,mid,L,R,v);
update(rs,mid+1,r,L,R,v);
pushup(x,l,r);
}
ll query(int x,int l,int r,int L,int R){
if(L>R||r<L||l>R) return 0;
if(L<=l&&r<=R) return sm[x];
int mid=(l+r)>>1;
pushdown(x,l,r);
return query(ls,l,mid,L,R)+query(rs,mid+1,r,L,R);
}
int queryl(int x,int l,int r,int p){
if(l==r)
return 1;
int mid=(l+r)>>1;
pushdown(x,l,r);
if(p<=mid) return queryl(ls,l,mid,p);
else{
int res=queryl(rs,mid+1,r,p);
if(res==p-mid&&rf[ls]==lf[rs])
return res+rb[ls];
else return res;
}
}
int queryr(int x,int l,int r,int p){
if(l==r)
return 1;
int mid=(l+r)>>1;
pushdown(x,l,r);
if(p<=mid){
int res=queryr(ls,l,mid,p);
if(res==mid-p+1&&rf[ls]==lf[rs])
return res+lb[rs];
else return res;
}else return queryr(rs,mid+1,r,p);
}
int n,m;
ll ans,a,b,c,tmp;
void calc(int x,ll y,ll f)
{(y>0)&&(ans=(ans+P+Q(3,y-1)*f*(ll)x%P)%P);}
signed main(){
int i,x,p,y;
scanf("%d",&n);
build(1,1,K);
for(i=1;i<=n;i++){
scanf("%d%lld",&m,&b);
a=query(1,1,K,m,m);
b-=query(1,1,K,1,m);
p=m;
if(b<=0)
goto END;
tmp=b;
while(b>0&&p>0){
x=queryl(1,1,K,p);
p-=x;
x=m-p;
calc(x,a,-1);
y=int(b%(ll)x);
if(p>0){
c=query(1,1,K,p,p);
if((c-a)*(ll)x<b){
b-=(c-a)*(ll)x;
calc(x,c,1);
a=c;
}else{
a+=b/(ll)x;
calc(y,a+1,1);
update(1,1,K,p+1,p+y,a+1);
calc(x-y,a,1);
update(1,1,K,p+y+1,p+x,a);
b=0;
}
}else{
a+=b/(ll)x;
calc(y,a+1,1);
update(1,1,K,1,y,a+1);
calc(x-y,a,1);
update(1,1,K,y+1,x,a);
}
}
b=tmp;
p=m+1;
if(p<=K)
a=query(1,1,K,p,p);
while(b>0&&p<=K){
x=queryr(1,1,K,p);
p+=x;
x=p-m-1;
calc(x,a,-1);
y=int(b%(ll)x);
if(p<=K){
c=query(1,1,K,p,p);
if((a-c)*(ll)x<b){
b-=(a-c)*(ll)x;
calc(x,c,1);
a=c;
}else{
a-=b/(ll)x;
calc(y,a-1,1);
update(1,1,K,p-y,p-1,a-1);
calc(x-y,a,1);
update(1,1,K,p-x,p-y-1,a);
b=0;
}
}else if(a*(ll)x>=b){
a-=b/(ll)x;
calc(y,a-1,1);
update(1,1,K,p-y,p-1,a-1);
calc(x-y,a,1);
update(1,1,K,p-x,p-y-1,a);
}else update(1,1,K,m+1,K,0);
}
END:;
printf("%lld\n",ans);
}return 0;
}