Yinchuan Regional 2019 Pot!!

Yinchuan Regional 2019
Pot!!
题目链接


题意:

有一个长为 n n n 的数组 a a a。初始全为 1 1 1 ,有两种操作:

  1. MULTIPLY l r x :表示给区间 [ l , r ] [l,r] [l,r] 上的数全部乘以 x x\quad x ( 2 ≤ x ≤ 10 ) (2\le x\le10) (2x10)
  2. MAX l r :表示询问区间 [ l , r ] [l,r] [l,r] 某个数的最大 质因数指数的最大值是多少。

原文:
对一个质数 p p p,如果 p m ∣ n p^m|n pmn 并且 p m + 1 ∤ n p^{m+1}\not|n pm+1n,则 p o t p ( n ) = m pot_p(n) = m potp(n)=m,第二种操作就是计算 : m a x   l ≤ i ≤ r { m a x   p ∣ a i { p o t p ( a i ) } } ( 1 ≤ l ≤ r ≤ n ) max_{\,l\le i\le r}\{max_{\,p|a_i}\{pot_p(a_i)\}\}(1\le l\le r\le n) maxlir{maxpai{potp(ai)}}(1lrn)的值

思路:

发现每个数的质因数只有 2 , 3 , 5 , 7 2,3,5,7 2,3,5,7,我们给一段区间所有数乘上 x x x 就相当于给这段区间所有数的四种质因子个数加上 x x x 的四种质因数个数,查询就是查询最大值。线段树模板题。

code:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e5+5;

int n,Q;

struct segement_tree{
	#define ls p<<1
	#define rs p<<1|1
	
	int n;
	struct info{
		int l2,l3,l5,l7;
		info(int x=0){
			l2=l3=l5=l7=0;
			switch(x){
				case 0:break;
				case 2:l2=1;break;
				case 3:l3=1;break;
				case 4:l2=2;break;
				case 5:l5=1;break;
				case 6:l2=1;l3=1;break;
				case 7:l7=1;break;
				case 8:l2=3;break;
				case 9:l3=2;break;
				case 10:l2=1;l5=1;break;
			}
		}
		info operator+(info x){
			info t;
			t.l2=l2+x.l2;
			t.l3=l3+x.l3;
			t.l5=l5+x.l5;
			t.l7=l7+x.l7;
			return t;
		}
	};
	struct Node{
		int mx;
		int n2,n3,n5,n7;
		info lazy;
		Node(){};
	}t[maxn<<2];
	
	void f(int p,info x){
		t[p].n2+=x.l2;
		t[p].n3+=x.l3;
		t[p].n5+=x.l5;
		t[p].n7+=x.l7;
		t[p].lazy=t[p].lazy+x;
		t[p].mx=max(max(t[p].n2,t[p].n3),max(t[p].n5,t[p].n7));
	}
	void push_down(int p){
		f(ls,t[p].lazy);
		f(rs,t[p].lazy);
		t[p].lazy=info();
	}
	Node merge_Node(Node a,Node b){
		Node c;
		c.n2=max(a.n2,b.n2);
		c.n3=max(a.n3,b.n3);
		c.n5=max(a.n5,b.n5);
		c.n7=max(a.n7,b.n7);
		c.mx=max(max(c.n2,c.n3),max(c.n5,c.n7));
		return c;
	}
	
	void build(int p,int l,int r){
		if(l==r)return;
		int mid=(l+r)>>1;
		build(ls,l,mid);
		build(rs,mid+1,r);
		t[p]=merge_Node(t[ls],t[rs]);
	}
	void build(int _n){
		n=_n;
		build(1,1,n);
	}
	
	void mul(int p,int l,int r,int L,int R,info x){
		if(L<=l && r<=R){
			f(p,x);
			return;
		}
		push_down(p);
		int mid=(l+r)>>1;
		if(L<=mid)mul(ls,l,mid,L,R,x);
		if(R>mid)mul(rs,mid+1,r,L,R,x);
		t[p]=merge_Node(t[ls],t[rs]);
	}
	void mul(int L,int R,int x){
		mul(1,1,n,L,R,info(x));
	}
	
	Node query(int p,int l,int r,int L,int R){
		if(L<=l && r<=R){
			return t[p];
		}
		push_down(p);
		int mid=(l+r)>>1;
		if(R<=mid)return query(ls,l,mid,L,R);
		if(L>mid)return query(rs,mid+1,r,L,R);
		return merge_Node(query(ls,l,mid,L,R),query(rs,mid+1,r,L,R));
	}
	int query(int L,int R){
		Node t=query(1,1,n,L,R);
		return t.mx;
	}
	
	void print(int p,int l,int r){
		printf("[%d,%d] %d\n",l,r,t[p].mx);
		printf("%d %d %d %d\n",t[p].n2,t[p].n3,t[p].n5,t[p].n7);
		printf("%d %d %d %d\n",t[p].lazy.l2,t[p].lazy.l3,t[p].lazy.l5,t[p].lazy.l7);
		if(l==r)return;
		int mid=(l+r)>>1;
		print(ls,l,mid);
		print(rs,mid+1,r);
	}
	void print(){
		print(1,1,n);
	}
	
	#undef ls
	#undef rs
}tr;

int main(){
	cin>>n>>Q;
	tr.build(n);
	
	for(int i=1;i<=Q;i++){
		string op;
		cin>>op;
		if(op=="MULTIPLY"){
			int l,r,x;
			cin>>l>>r>>x;
			tr.mul(l,r,x);
		}
		else {
			int l,r;
			cin>>l>>r;
			cout<<"ANSWER "<<tr.query(l,r)<<endl;
		}
	}
	return 0;
}
  • 28
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值