列表

详情


NC16034. 修改序列值

描述

维护一个长度为n的正整数序列a[1],a[2]...a[n],支持修改序列中指定位置的值
每次修改后问对序列重复进行以下操作,需要进行几次操作才能使序列变为全0(询问后序列和询问前相同,不会变为全0):
选出序列中最大值的出现位置,若有多个最大值则选位置标号最小的一个,设位置为x,则将a[x-1],a[x],a[x+1]的值减1,如果序列中存在小于0的数,则把对应的数改为0

输入描述

第一行一个整数n
接下来n行,每行一个整数a[i]
接下来一行一个整数q
接下来q行,每行两个用空格分隔的整数x[i],y[i],表示把a[x[i]]修改为y[i]

输出描述

q行,每行一个整数表示答案

示例1

输入:

4
3
6
6
4
3
4 4
3 5
1 8

输出:

10
10
13

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 161ms, 内存消耗: 16348K, 提交时间: 2018-05-29 21:32:04

#include<iostream>
#include<cstdlib>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
const long long inf=1e18;
int a[110000],n,num_q,na[110000];
struct segment_tree
{
     int l,r;
     bool pl,pr,cover[2];
     long long sum[2][2];
};
segment_tree awp;
segment_tree tree[1<<18];
void merge(segment_tree ll,segment_tree rr,segment_tree &now)
{
     int i,j,s,p,q;
     now.pl=ll.pl;
     now.cover[0]=now.cover[1]=false;
     if(ll.cover[0]&&a[ll.r]<a[rr.l])
     {
     	now.pl^=rr.pl;
        if(rr.cover[0])
           now.cover[0]=true;
	 }
	 now.pr=rr.pr;
	 if(rr.cover[1]&&a[ll.r]>=a[rr.l])
	 {
 		 now.pr^=ll.pr;
 		 if(ll.cover[1])
 		    now.cover[1]=true;
 	 }
 	 for(i=0;i<2;i++)
 	    for(j=0;j<2;j++)
	    {
 	        if(a[ll.r]>=a[rr.l])
 	        { 
 	        	if(!ll.cover[1])
         	     	now.sum[i][j]=ll.sum[i][0]+rr.sum[ll.pr][j];
    	     	else
  	     	        now.sum[i][j]=ll.sum[i][0]+rr.sum[ll.pr^i][j];
            }
            else
            {
            	if(!rr.cover[0])
        	       now.sum[i][j]=ll.sum[i][rr.pl]+rr.sum[0][j];
     	       else
     	       {
     	           now.sum[i][j]=ll.sum[i][rr.pl^j]+rr.sum[0][j];
     	       }
			}
 	    }
}
void build(int left,int right,int id)
{
    int i,j,l=2*id+1,r=2*id+2,mid=(left+right)>>1;
    tree[id].l=left;
    tree[id].r=right;
    if(left==right)
    {
        for(i=0;i<2;i++) 
          for(j=0;j<2;j++)
             tree[id].sum[i][j]=0;
        tree[id].sum[0][0]=a[left];
        tree[id].cover[0]=tree[id].cover[1]=true;
        tree[id].pl=tree[id].pr=1;
        return;
    }
    build(left,mid,l);
    build(mid+1,right,r);
    merge(tree[l],tree[r],tree[id]);
}
void update(int pos,int y,int id)
{
    int l=2*id+1,r=2*id+2,i,j,left,right;
    left=tree[id].l;
    right=tree[id].r;
    if(left==right)
    {
       for(i=0;i<2;i++) 
          for(j=0;j<2;j++)
             tree[id].sum[i][j]=0;
        tree[id].sum[0][0]=a[left];
        tree[id].pl=tree[id].pr=1; 
	    tree[id].cover[0]=tree[id].cover[1]=true;   
        return;
    }
    if(tree[l].r<pos)
       update(pos,y,r);
    else
       update(pos,y,l);
    merge(tree[l],tree[r],tree[id]); 
}
int main()
{
    scanf("%d",&n);
    int i,j,s,p,q,x,y;
    for(i=0;i<n;i++)
       scanf("%d",&a[i]);
    build(0,n-1,0);
    scanf("%d",&num_q);
    while(num_q--)
    {
        scanf("%d%d",&x,&y);
        x--;
        a[x]=y;
        update(x,y,0);
        printf("%lld\n",tree[0].sum[0][0]);
    }
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 178ms, 内存消耗: 6496K, 提交时间: 2018-05-25 20:29:37

#include<bits/stdc++.h>
#define ll long long
#define inf 1000000000
#define pb push_back
#define vi vector<int>
#define vll vector<ll>
#define fi first
#define se second
#define mpr make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define up(x,y) (x<(y)?x=(y):0)
#define dn(x,y) (x>(y)?x=(y):0)
#define ad(x,y) x=(x+(y))%mod
#define N 100009
using namespace std;

int n,m,a[N],b[N];
struct node{ ll ans; bool u,v; }T[N<<2][2][2];
node solve(int l,int r){
	if (l>r) return (node){0,0,0};
	int i,k; ll ans=0; bool u=0,v=0;
	for (i=l; i<=r; i++) b[i]=a[i];
	while (1){
		for (i=k=l; i<=r; i++) if (b[i]>b[k]) k=i;
		if (b[k]<=0) return (node){ans,u,v};
		if (k==l) u=1; if (k==r) v=1;
		ans+=b[k]; b[k-1]=b[k]=b[k+1]=0;
	}
}
node mrg(node x,node y){
	return (node){x.ans+y.ans,x.u,y.v};
}
void mrg(int k,int l,int r){
	int i,j,mid=l+r>>1;
	for (i=0; i<2; i++)
		for (j=0; j<2; j++)
			if (a[mid]>=a[mid+1])
				T[k][i][j]=mrg(T[k<<1][i][0],T[k<<1|1][T[k<<1][i][0].v][j]);
			else
				T[k][i][j]=mrg(T[k<<1][i][T[k<<1|1][0][j].u],T[k<<1|1][0][j]);
}
void build(int k,int l,int r){
	if (r-l<=5){
		int i,j;
		for (i=0; i<2; i++)
			for (j=0; j<2; j++) T[k][i][j]=solve(l+i,r-j);
		return;
	}
	int mid=l+r>>1;
	build(k<<1,l,mid); build(k<<1|1,mid+1,r);
	mrg(k,l,r);
}
void mdy(int k,int l,int r,int x){
	if (r-l<=5){
		int i,j;
		for (i=0; i<2; i++)
			for (j=0; j<2; j++) T[k][i][j]=solve(l+i,r-j);
		return;
	}
	int mid=l+r>>1;
	if (x<=mid) mdy(k<<1,l,mid,x); else mdy(k<<1|1,mid+1,r,x);
	mrg(k,l,r);
}
int main(){
	scanf("%d",&n);
	int i,x,y;
	for (i=1; i<=n; i++) scanf("%d",&a[i]);
	build(1,1,n);
	scanf("%d",&m);
	while (m--){
		scanf("%d%d",&x,&y);
		a[x]=y; mdy(1,1,n,x);
		printf("%lld\n",T[1][0][0].ans);	
	}
	return 0;
}

上一题