2019ICPC银川 Pot

因为只有乘2 − 10直接的质数只有2 , 3 , 5 , 7 ,要保证m最大我们肯定只考虑2 , 3 , 5 , 7,这样看每次乘的数然后分解为2 , 3 , 5 , 7 ,建立四颗线段树维护最值就行了。

这道题是我的线段树入门题,注意最大最小值的树当l==r时懒标记如何下放。注意最大最小值在建树和查询以及后面的查询都要用到。

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n;i>=a;i--) 
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int maxn=100005;
ll n,m,a[maxn],ans[8][maxn<<2],tag[8][maxn<<2],id;
inline ll ls(ll x)
{
	return x<<1;
}
inline ll rs(ll x)
{
	return x<<1|1;
}
void push_up(ll p,ll id)
{
	if(ans[id][ls(p)]!=0||ans[id][rs(p)]!=0)
	ans[id][p]=max(ans[id][ls(p)],ans[id][rs(p)]);
}//ans 为线段树内存储的值
void build(ll p,ll l,ll r,ll id)//p pos position 就是id的意思 
{
	tag[id][p]=0;//重设标记 
	if(l==r)
	{
		ans[id][p]=a[l];
		return;
	}
	ll mid=(l+r)>>1;
	build(ls(p),l,mid,id);
	build(rs(p),mid+1,r,id);
	ans[id][p]=max(ans[id][ls(p)],ans[id][rs(p)]);//将值上传
}
inline void f(ll p,ll l,ll r,ll k,ll id)//一段区间内,对所有tag更新,并对所有ans更新,k为父节点的tag,用来更新子节点的tag和值 
{
	tag[id][p]=tag[id][p]+k;
	ans[id][p]=ans[id][p]+k;
}
inline void push_down(ll p,ll l,ll r,ll id)//懒标记下放, 
{
	ll mid=(l+r)>>1;
	f(ls(p),l,mid,tag[id][p],id);
	f(rs(p),mid+1,r,tag[id][p],id);
	tag[id][p]=0;
}//该两个函数的作用为更新l到r这一段区间的lazy tag 
inline void update(ll nl,ll nr,ll l,ll r,ll p,ll k,ll id)//对每个数加上k的操作 nl,nr为查询区 
{
	if(nl<=l&&r<=nr)//如果该区域完全被被查询区域包含
	{
		ans[id][p]+=k;//数组值增加,打上懒标记
		tag[id][p]+=k;
		return;
	}
	push_down(p,l,r,id);
	ll mid=(l+r)>>1;
	if(nl<=mid) update(nl,nr,l,mid,ls(p),k,id);
	if(nr> mid) update(nl,nr,mid+1,r,rs(p),k,id);
	push_up(p,id);//将更新后的值上传,保证更改过的值的上层节点都满足线段树要求 
}
ll query(ll q_x,ll q_y,ll l,ll r,ll p,ll id)
{
	if(q_x<=l&&r<=q_y)return ans[id][p];//如果该段区间完全被包含,则返回该段区间的值。此时懒标记已全部更新 
	ll mid=(l+r)>>1;
	push_down(p,l,r,id);//逐步下放懒标记
	ll maxl=-1,maxr=-1;
	if(q_x<=mid)maxl=query(q_x,q_y,l,mid,ls(p),id);//两个if不干扰,大部分情况只是将查询的线段分为两个部分查询 
	if(q_y>mid)maxr=query(q_x,q_y,mid+1,r,rs(p),id);
	return max(maxl,maxr);
}
/*void debug(int debug_1)
{
	if(ans[debug_1]==0)return ;
	cout<<ans[debug_1]<<' ';
	debug(ls(debug_1));
	debug(rs(debug_1));
}*/
ll tmp[14],nowtmp;
int main()
{
	ios
	ll b,c,d,e,f;
	cin>>n>>m;
	//for(int i=1;i<=n*4;i++)cout<<ans[i]<<' ';cout<<endl;
	//debug(1);cout<<endl;
	char str[100];
	while(m--)
	{
		cin>>str;
		if(str[1]=='U')
		{
			cin>>b>>c>>d;//bl  cr  d dis
			nowtmp=0;
			for(int j=2;j<=d*d;j++)
			{
				while(d%j==0)
				{
					tmp[++nowtmp]=j;
					d/=j;
				}
			}
			if(!d)tmp[++nowtmp]=d;
			for(int i=1;i<=nowtmp;i++)
			{
				update(b,c,1,n,1,1,tmp[i]);//aa
			}	
			/*rep(i,2,8)
			{
				cout<<i<<' ';
				for(int j=1;j<=n;j++)
				{
					cout<<query(j,j,1,n,1,i)<<' ';
				}
				cout<<endl;
			}
			for(int j=2;j<=7;j++)
			{
				cout<<j<<' ';
				for(int i=1;i<=n*4;i++)cout<<ans[j][i]<<' ';cout<<endl;
			}*/
			//debug(1);cout<<endl;
		}
		//for(int i=1;i<=n*4;i++)cout<<ans[i]<<' ';cout<<endl;
		if(str[1]=='A')
		{
			cin>>e>>f;
			int max1=max(query(e,f,1,n,1,2),query(e,f,1,n,1,3));
			int max2=max(query(e,f,1,n,1,5),query(e,f,1,n,1,7));
			cout<<"ANSWER "<<max(max1,max2)<<endl;//p是查询起点
		}
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值