[CFR512 div 2 F]Putting Boxes Together(线段树)

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 }

 

上一篇:Leetcode 546.移除盒子


下一篇:瀑布流软加载