http://codeforces.com/blog/entry/62013
两个结论:
1.一定有一个箱子不用动。
2.不动的箱子一定是加权前缀和为S/2的那个。
1显然,2由1易得。
于是问题变为:求一段区间前缀和>S/2的第一个数的位置。显然先求出S/2,再线段树上二分即可,实现过程见代码。
自定义struct比stl:pair快,注意取模和爆long long的问题。
1 #include<cstdio> 2 #include<algorithm> 3 #define ls (x<<1) 4 #define rs (ls|1) 5 #define lson ls,L,mid 6 #define rson rs,mid+1,R 7 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 8 typedef long long ll; 9 using namespace std; 10 11 const int N=200010,inf=1e9,mod=1e9+7; 12 int n,Q,x,y,a[N],w[N]; 13 struct Tr{ ll s1,s2; }v[N<<2]; 14 struct P{ ll x,y; }; 15 16 void upd(int x){ v[x].s1=v[ls].s1+v[rs].s1; v[x].s2=(v[ls].s2+v[rs].s2)%mod; } 17 18 void build(int x,int L,int R){ 19 if (L==R){ v[x].s1=w[L]; v[x].s2=1ll*a[L]*w[L]%mod; return; } 20 int mid=(L+R)>>1; 21 build(lson); build(rson); upd(x); 22 } 23 24 void mdf(int x,int L,int R,int pos,int k){ 25 if (L==R){ v[x].s1=k; v[x].s2=1ll*a[pos]*k%mod; return; } 26 int mid=(L+R)>>1; 27 if (pos<=mid) mdf(lson,pos,k); else mdf(rson,pos,k); 28 upd(x); 29 } 30 31 P que(int x,int L,int R,int l,int r){ 32 if (L==l && r==R) return (P){v[x].s1,v[x].s2}; 33 int mid=(L+R)>>1; 34 if (r<=mid) return que(lson,l,r); 35 else if (l>mid) return que(rson,l,r); 36 else{ 37 P s1=que(lson,l,mid),s2=que(rson,mid+1,r); 38 return (P){s1.x+s2.x,(s1.y+s2.y)%mod}; 39 } 40 } 41 42 P ask(int x,int L,int R,int l,int r,ll k){ 43 if (L==l && r==R){ 44 if (v[x].s1<=k) return (P){inf,v[x].s1}; 45 if (L==R) return (P){l,0}; 46 } 47 int mid=(L+R)>>1; 48 if (r<=mid) return ask(lson,l,r,k); 49 else if (l>mid) return ask(rson,l,r,k); 50 else{ 51 ll sm=0,res=inf; 52 P cur=ask(lson,l,mid,k); 53 res=min(res,cur.x); sm+=cur.y; 54 if (res<inf) return (P){res,sm}; 55 cur=ask(rson,mid+1,r,k-sm); 56 res=min(res,cur.x); sm+=cur.y; 57 return (P){res,sm}; 58 } 59 } 60 61 int work(int l,int r){ 62 int k=ask(1,1,n,l,r,que(1,1,n,l,r).x/2).x; 63 P t1=(k==l) ? (P){0,0} : que(1,1,n,l,k-1),t2=que(1,1,n,k,r); 64 return ((a[k]*(t1.x%mod)-t1.y+t2.y-a[k]*(t2.x%mod))%mod+mod)%mod; 65 } 66 67 int main(){ 68 freopen("1058f.in","r",stdin); 69 freopen("1058f.out","w",stdout); 70 scanf("%d%d",&n,&Q); 71 rep(i,1,n) scanf("%d",&a[i]),a[i]=a[i]-i; 72 rep(i,1,n) scanf("%d",&w[i]); 73 build(1,1,n); 74 while (Q--){ 75 scanf("%d%d",&x,&y); 76 if (x<0) mdf(1,1,n,-x,y); else printf("%d\n",work(x,y)); 77 } 78 return 0; 79 }