[二分][树状数组] Jzoj P5871 挑战

Description

 

Input

Output

 

Sample Input

10 7
0 3 1 4 6 2 7 8 10 1
2 5
1 3
9 36
4 10
4 9
1 2
1 0

Sample Output

1
-1
9
-1
4
-1
1
 

Data Constraint

题解

  • 首先,先将所有数加入树状数组里,求出在没修改前的ans
  • 然后,修改后,将相应位置的树状数组里加上y-p[x]
  • 如果,修改的位置大于ans的位置,则输出ans
  • 否则,判断1~x-1是否等于x
  • 若不等于,则二分出一个mid,为最小大于当前x两倍的位置
  • while一直找,知道找到相等的

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 using namespace std;
 4 int n,m,sum,ans,p[200010],sz[200010];
 5 void insert(int x,int y) { for (;x<=n;x+=x&-x) sz[x]+=y; }
 6 int query(int x)
 7 {
 8     int r=0;
 9     for (;x;x-=x&-x) r+=sz[x];
10     return r;
11 }
12 int ef(int x)
13 {
14     int mx=query(x),l=x+1,r=n,mid,ans=0;
15     while (l<=r)
16     {
17         mid=(l+r)>>1;
18         if (query(mid)>=mx*2) r=mid-1,ans=mid; else l=mid+1;
19     }
20     return ans;
21 }
22 int main()
23 {
24     freopen("challenge.in","r",stdin);
25     freopen("challenge.out","w",stdout);
26     scanf("%d%d",&n,&m),ans=n+1;
27     for (int i=1;i<=n;i++) 
28     {
29         scanf("%d",&p[i]);
30         insert(i,p[i]);
31         if (p[i]==sum) ans=min(ans,i);
32         sum+=p[i];
33     }
34     for (int i=1;i<=m;i++)
35     {
36         int x,y;
37         scanf("%d%d",&x,&y);
38         insert(x,y-p[x]),p[x]=y;
39         if (x>ans) printf("%d\n",ans);
40         else 
41         {
42             ans=n+1;
43             if (query(x)==query(x-1)*2)    ans=x;
44             else
45             {
46                 while(x<=n)
47                 {
48                     int y=ef(x);
49                     if (y==0) break;
50                     if (query(y)==query(y-1)*2)
51                     {
52                         ans=y;
53                         break;
54                     }
55                     x=y;
56                 }
57             }
58             if (ans==n+1) printf("-1\n"); else printf("%d\n",ans);
59         }
60     }
61     return 0;
62 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9688512.html