列表

详情


NC200195. 区区区间

描述

 特别喜欢线段树,他给你一个长度为  的序列,对序列进行 次操作。

操作有两种:

 :表示将下标在  区间内的数字替换成

 :表示查询区间  的区间和

输入描述

第一行两个整数 ,表示序列的长度和操作次数

第二行  个整数,表示序列的初始值 

接下来  行,每行三或四个数字,若第一个数字是 ,则表示操作 ,反之则表示操作

输出描述

对于每个操作 ,输出一行一个整数表示区间和。

示例1

输入:

5 5
1 1 1 1 1
2 1 5
1 1 5 1
2 1 5
1 1 3 3
2 1 3

输出:

5
15
12

说明:

第一次1操作后,序列是1 2 3 4 5
第二次1操作后,序列是3 4 5 4 5

原站题解

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

C++14(g++5.4) 解法, 执行用时: 668ms, 内存消耗: 16304K, 提交时间: 2019-12-21 22:39:24

#include<bits/stdc++.h>
using namespace std;
#define ll long long 

const int N=2e5+100;

ll t[N<<2],lzy[N<<2];
ll a[N];
#define ls x<<1
#define rs x<<1|1


void pushdown(int x,int l,int r)
{
	if(lzy[x])
	{
		int mid=l+r>>1;
		lzy[ls]=lzy[x];
		lzy[rs]=lzy[x]+mid-l+1;
		t[ls]=(lzy[x]+lzy[x]+mid-l)*(mid-l+1)/2;
		t[rs]=(lzy[rs]+lzy[rs]+r-mid-1)*(r-mid)/2;
		lzy[x]=0;
	}
}
void build(int l,int r,int x)
{
	if(l==r) 
	{
		t[x]=a[l];
		return ;
	}
	int mid=l+r>>1;
	build(l,mid,ls);
	build(mid+1,r,rs);
	t[x]=t[ls]+t[rs];
}
void update(int l,int r,int L,int R,int x,int k)
{
	if(L<=l&&r<=R)
	{
		t[x]=1ll*(k+l-L+k+l-L+r-l)*(r-l+1)/2;
		lzy[x]=k+l-L;
		return ;
	}
	pushdown(x,l,r);
	int mid=l+r>>1;
	if(L<=mid) update(l,mid,L,R,ls,k);
	if(R>mid) update(mid+1,r,L,R,rs,k);
	t[x]=t[ls]+t[rs]; 
}
ll query(int l,int r,int L,int R,int x)
{
	if(L<=l&&r<=R) return t[x];
	pushdown(x,l,r);
	int mid=l+r>>1;
	ll ans=0;
	if(L<=mid) ans+=query(l,mid,L,R,ls);
	if(R>mid) ans+=query(mid+1,r,L,R,rs);
	return ans; 
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)  scanf("%d",&a[i]);
	build(1,n,1);
	while(m--)
	{
		int op,x,y,z;
		scanf("%d%d%d",&op,&x,&y);
		if(op==1)
		{
			scanf("%d",&z);
			update(1,n,x,y,1,z);
		}
		else cout<<query(1,n,x,y,1)<<endl;
	}
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 399ms, 内存消耗: 18912K, 提交时间: 2020-02-25 13:28:59

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c))
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x;
}
struct node
{
	int l,r;
	long long v;
	bool operator <(const node &tmp)const
	{
		return l<tmp.l;
	}
};
set<node>s;
typedef set<node>::iterator It;
It split(int pos)
{
	It it=s.lower_bound({pos,0,0});
	if(it!=s.end()&&it->l==pos) return it;
	--it;
	if(pos>it->r)return s.end();
	int l=it->l,r=it->r,v=it->v;
	s.erase(it);
	s.insert({l,pos-1,v});
	return s.insert({pos,r,v+pos-l}).first;
}
void _assign(int l,int r,int v)
{
	It R=split(r+1),L=split(l);
	s.erase(L,R);
	s.insert({l,r,v});
}
long long query(int l,int r)
{
	It R=split(r+1),L=split(l);
	long long ans=0;
	for(It it=L;it!=R;++it)
	{
		long long len=it->r-it->l+1;
		ans+=it->v*len+len*(len-1)/2;
	 } 
	 return ans;
}
int main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
	s.insert({i,i,read()});
	while(m--)
	{
		int op,l,r,k;
		scanf("%d %d %d",&op,&l,&r);
		if(op==1)
		{
			scanf("%d",&k);
			_assign(l,r,k);
		}
		else
		printf("%lld\n",query(l,r));
	}
}

上一题