JZOJ-senior-5943. 【NOIP2018模拟11.01】树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HuangXinyue1017/article/details/83821764

Time Limits: 1000 ms Memory Limits: 262144 KB

Description

在这里插入图片描述

Input

第一行一个整数 n 表示序列长度, 接下来一行 n 个整数描述这个序列.
第三行一个整数 q 表示操作次数, 接下来 q 行每行一次操作, 格式同题目描述.

Output

输出等同于操作 2, 3 次数之和的行数, 每行一个非负整数表示对应询问的答案. 注意操作 2 的答案不需要进行取模.

Sample Input

Sample Input1
5
8 4 3 5 6
5
2 3 5
3 1 2
1 2 4 3
2 3 5
3 1 2

样例 2
见下发文件中的 ex_seg2.in/out.

Sample Output

Sample Output1
14
608
10
384

样例 1 解释
第三次操作后, 序列变为 [8, 0, 3, 1, 6].

Data Constraint

对于前 30% 的数据, n, q ≤ 100;
对于另 20% 的数据, 没有操作 1;
对于另 20% 的数据, 没有操作 3;
对于 100% 的数据, n, q ≤ 10^5, ai ≤ 10^9, k ≤ 2^30, 1 ≤ l ≤ r ≤ n.

Solution

每次修改只会让数变小,一个数最多只会被修改 l o g log
我们用线段树维护一个区间是否有修改的必要(用区间的或值来判断),需要修改就暴力修改
对于操作三,把式子展开,再维护一个区间平方和就行了
时间复杂度 O ( n l o g 2 n ) O(nlog^2n)

Code

#include<algorithm>
#include<cstdio>
#include<cctype>

#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
#define ll long long
#define L x<<1
#define R L|1

using namespace std;

const int N=1e5+5,P=998244353;
int n,m,t,opl,opr,k,a[N];
struct node{ll s1; int s2,p;}tr[4*N];

inline void read(int &n)
{
	int x=0,w=0; char ch=0;
	while(!isdigit(ch)) w|=ch=='-',ch=getchar();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	n=w?-x:x;
}

void update(int x)
{
	tr[x].s1=tr[L].s1+tr[R].s1;
	tr[x].s2=(tr[L].s2+tr[R].s2)%P;
	tr[x].p=tr[L].p|tr[R].p;
}

void build(int x,int l,int r)
{
	if(l==r)
	{
		tr[x].s1=a[l];
		tr[x].s2=(ll)a[l]*(ll)a[l]%P;
		tr[x].p=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(L,l,mid),build(R,mid+1,r);
	update(x);
}

void modify(int x,int st,int en,int l,int r)
{
	if(st==en)
	{
		tr[x].s1&=k;
		tr[x].s2=(ll)tr[x].s1*(ll)tr[x].s1%P;
		tr[x].p=tr[x].s1;
		return;
	}
	int mid=(st+en)>>1;
	if(r<=mid)
	{
		if((tr[L].p&k)<tr[L].p) modify(L,st,mid,l,r);
	}
	else if(l>mid)
	{
		if((tr[R].p&k)<tr[R].p) modify(R,mid+1,en,l,r);
	}
	else
	{
		if((tr[L].p&k)<tr[L].p) modify(L,st,mid,l,mid);
		if((tr[R].p&k)<tr[R].p) modify(R,mid+1,en,mid+1,r);
	}
	update(x);
}

node ask(int x,int st,int en,int l,int r)
{
	if(st==l&&en==r) return tr[x];
	int mid=(st+en)>>1;
	if(r<=mid) return ask(L,st,mid,l,r);
	else if(l>mid) return ask(R,mid+1,en,l,r);
	else
	{
		node b1=ask(L,st,mid,l,mid);
		node b2=ask(R,mid+1,en,mid+1,r);
		return (node){b1.s1+b2.s1,(b1.s2+b2.s2)%P,0};
	}
}

int main()
{
	freopen("seg.in","r",stdin);
	freopen("seg.out","w",stdout);
	read(n);
	fo(i,1,n) read(a[i]);
	build(1,1,n);
	read(m);
	fo(i,1,m)
	{
		read(t),read(opl),read(opr);
		if(t==1)
		{
			read(k);
			modify(1,1,n,opl,opr);
			continue;
		}
		node e=ask(1,1,n,opl,opr);
		ll ans=0;
		if(t==2) ans=e.s1;
		else
		{
			e.s1%=P,e.s2%=P;
			ans=((ll)2*(ll)(opr-opl+1)%P*(ll)e.s2%P+(ll)2*(ll)e.s1%P*(ll)e.s1%P)%P;
		}
		printf("%lld\n",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/HuangXinyue1017/article/details/83821764