NOIP模拟 挑战challenge

NOIP模拟 挑战challenge_第1张图片NOIP模拟 挑战challenge_第2张图片

  • 我们看到这道题首先想到的当然是直接暴力
  • 然后我们发现如果上一次的答案为x,若修改的点在x点后,那么答案不会改变
  • 如果在x前,我们用树状数组维护一个值就行了
  • 下面是代码
#include
#define lowbit(x) x&-x
using namespace std;
typedef long long ll;
const ll N=2e5+10;
void In(ll &x)
{
	ll f = 1;
	x = 0;
	char s = getchar();
	while (s < '0' || s > '9')
	{
		if(s == '-') f = -1;
		s = getchar();
	}
	while (s >= '0' && s <= '9')
	{
		x = x * 10 + s - '0';
		s = getchar();
	}
	x = x * f;
}
void Out(ll x)
{
	if (x < 0)
	{
		putchar('-');
		x = -x;
	}
	if (x > 9)
	{
		Out(x/10);
	}
	putchar(x%10 + '0');
}
ll t[N],a[N];
ll n,m;
void add(ll x,ll to) {
    for (ll i = x; i <= n; i += lowbit(i))
		t[i] += to;
}

ll Get(ll x) {
    ll ans = 0;
    for (ll i = x; i; i -= lowbit(i))
		ans += t[i];
    return ans;
}

int Search(ll x) {
    ll ans = n + 1,
	   l = x + 1,
	   r = n;
    ll sum = Get(x);
    while (l <= r)
	{
        ll mid = l + r >> 1;
        if (Get(mid) >= sum * 2ll)
        {
        	r = mid - 1; 
        	ans = mid;
		}
		else l = mid + 1;
    }
    return ans;
}

int main()
{
	In(n);
	In(m);
    ll sum = 0;
    ll ans = n + 1;
    for (ll i = 1; i <= n; i++)
	{
		In(a[i]);
        add(i,a[i]);
        if (ans > n && sum == a[i])
			ans = i;
        sum += a[i];
    }
    for (ll i = 1; i <= m; i++)
	{
        ll x;
        ll y;
        In(x);
        In(y);
        add(x,y-a[x]);
		a[x]=y;
        if (x > ans)
		{
			Out(ans);
			putchar('\n');
            continue;
        }
        ans = n + 1;
        if (Get(x - 1) * 2ll == Get(x))
			ans = x;
        else while (x <= n)
		{
            ll now = Search(x);
            if (!now) break;
            if (Get(now - 1) * 2ll == Get(now))
			{
                ans = now;
                break;
            }
            x = now;
        }
        Out(ans>n?-1:ans);
        putchar('\n');
    }
    return 0;
}

你可能感兴趣的:(NOIP模拟 挑战challenge)