[线段树] BZOJ 4499 线性函数

本文介绍了一种高效的线段树实现方式,并通过一个具体的代码示例详细展示了如何使用快速读取技巧、模块化算术等技术进行节点操作。文章重点讲解了线段树的构建、更新及查询操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


好裸的线段树


#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define P 1000000007
using namespace std;
typedef long long ll;

inline char nc(){
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(int &x){
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

inline void read(ll &x){
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

inline void read(char &x){
	for (x=nc();x!='M' && x!='Q';x=nc());
}

struct node{
	ll k,b;
	node(ll k=1,ll b=0):k(k),b(b) { }
	void scan(){
		read(k); read(b);
	}
	friend node operator + (const node &A,const node &B){
		node ret;
		(ret.k=B.k*A.k)%=P;
		(ret.b=B.k*A.b%P+B.b)%=P;
		return ret;
	}
};

struct SEGTREE{
	node T[800005];
	int M,TH;
	inline void Build(int n,node *a){
		for (M=1;M<n+2;M<<=1,TH++);
		for (int i=1;i<=n;i++)
			T[M+i]=a[i];
		for (int i=M-1;i;i--)
			T[i]=T[i<<1]+T[i<<1|1];
	}
	inline void Change(int s,node x){
		T[s+=M]=x;
		while (s>>=1)
			T[s]=T[s<<1]+T[s<<1|1];
	}
	inline node Query(int s,int t){
		node lret,rret;
		for (s+=M-1,t+=M+1;s^t^1;s>>=1,t>>=1)
		{
			if (~s&1) lret=lret+T[s^1];
			if ( t&1) rret=T[t^1]+rret;
		}
		return lret+rret;
	}
}SEG;

int n,Q;
node a[200005];

int main()
{
	ll ans;
	char order;
	int l,r,x;
	node itmp;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(n); read(Q);
	for (int i=1;i<=n;i++)
		a[i].scan();
	SEG.Build(n,a);
	while (Q--)
	{
		read(order);
		if (order=='M')
		{
			read(l); itmp.scan();
			SEG.Change(l,itmp);
		}
		else if (order=='Q')
		{
			read(l); read(r); read(x);
			node ret=SEG.Query(l,r);
			(ans=ret.k*x+ret.b)%=P;
			printf("%lld\n",ans);
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值