[2019 icpc 银川区域赛] G Pot!! 线段树区间查询

题目链接:G Pot!!

题意

给你一个长度为n初始化为1的序列。你有两个操作

  1. 给区间[l,r]里每一个数乘以v。
  2. 查询区间里的一个最大值。

这个最大值题目中有定义,其实知道唯一分解定理就不难理解,这个最大值就是一个数唯一分解后,所有质因数里最大的幂次。然后在区间[l,r]里面找每个数最大幂次的最大值。

题解

本题的入手点在于给区间乘以一个数v的大小≤10,10以内的数唯一分解后,无非2、3、5、7四种。言外之意,无论我如何乘,都只能是2,3,5,7这四个数的幂次方。我们可以建立一个线段树维护5个点,2,3,5,7的幂次以及这四个幂次中的最大值。

注意我们在设置lazy标记的时候也要设立2,3,5,7的幂次,往下push完重置为0即可。

代码

一颗线段是维护4个点

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
//extern "C"{void *__dso_handle=0;}
typedef long long ll;
typedef long double ld;
//typedef int fuck;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define lowbit(x) x&-x
//#define int long long

const double PI=acos(-1.0);
const double eps=1e-6;
const ll mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=1e5+10;
const int maxm=100+10;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

int n,q;
struct Tree
{
    
    
	int maxx;
	int num2,num3,num5,num7;
}tree[maxn<<2];

struct Lazy
{
    
    
	int num;
	int num2,num3,num5,num7;
}lazy[maxn<<2];

int prime[5]={
    
    2,3,5,7};

void pushup(int p)
{
    
    
	tree[p].maxx=max(tree[p*2].maxx,tree[p*2+1].maxx);
	tree[p].num2=max(tree[p*2].num2,tree[p*2+1].num2);
	tree[p].num3=max(tree[p*2].num3,tree[p*2+1].num3);
	tree[p].num5=max(tree[p*2].num5,tree[p*2+1].num5);
	tree[p].num7=max(tree[p*2].num7,tree[p*2+1].num7);
}

void build(int p,int l,int r)
{
    
    
	lazy[p].num=lazy[p].num2=lazy[p].num3=lazy[p].num5=lazy[p].num7=0;
	if(l==r) {
    
     
		tree[p].maxx=tree[p].num2=tree[p].num3=tree[p].num5=tree[p].num7=0;
		return ;
	}
	int mid=l+(r-l)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	pushup(p);
}
void pushdown(int p)
{
    
    
	if(!lazy[p].num) return ;
	lazy[p*2].num=lazy[p*2+1].num=1;
	
	lazy[p*2].num2+=lazy[p].num2;
	lazy[p*2].num3+=lazy[p].num3;
	lazy[p*2].num5+=lazy[p].num5;
	lazy[p*2].num7+=lazy[p].num7;
	
	lazy[p*2+1].num2+=lazy[p].num2;
	lazy[p*2+1].num3+=lazy[p].num3;
	lazy[p*2+1].num5+=lazy[p].num5;
	lazy[p*2+1].num7+=lazy[p].num7;
	
	tree[p*2].num2+=lazy[p].num2, tree[p*2].maxx=max(tree[p*2].maxx,tree[p*2].num2); 
	tree[p*2].num3+=lazy[p].num3, tree[p*2].maxx=max(tree[p*2].maxx,tree[p*2].num3); 
	tree[p*2].num5+=lazy[p].num5, tree[p*2].maxx=max(tree[p*2].maxx,tree[p*2].num5); 
	tree[p*2].num7+=lazy[p].num7, tree[p*2].maxx=max(tree[p*2].maxx,tree[p*2].num7); 
	
	tree[p*2+1].num2+=lazy[p].num2, tree[p*2+1].maxx=max(tree[p*2+1].maxx,tree[p*2+1].num2); 
	tree[p*2+1].num3+=lazy[p].num3, tree[p*2+1].maxx=max(tree[p*2+1].maxx,tree[p*2+1].num3); 
	tree[p*2+1].num5+=lazy[p].num5, tree[p*2+1].maxx=max(tree[p*2+1].maxx,tree[p*2+1].num5); 
	tree[p*2+1].num7+=lazy[p].num7, tree[p*2+1].maxx=max(tree[p*2+1].maxx,tree[p*2+1].num7); 
	
	lazy[p].num2=lazy[p].num3=lazy[p].num5=lazy[p].num7=0;
	lazy[p].num=0;
}

void multi(int p,int l,int r,int ml,int mr,int v)
{
    
    
	if(ml<=l && mr>=r)
	{
    
    
		lazy[p].num=1;
		int tmp=v;
		for(int i=0;i<4;i++)
		{
    
    
			int cnt=0; 
			while(tmp%prime[i]==0)
			{
    
    
				tmp/=prime[i];
				cnt++;
			}
			if(i==0) {
    
     lazy[p].num2+=cnt,tree[p].num2+=cnt, tree[p].maxx=max(tree[p].maxx,tree[p].num2); }
			if(i==1) {
    
     lazy[p].num3+=cnt,tree[p].num3+=cnt, tree[p].maxx=max(tree[p].maxx,tree[p].num3); }
			if(i==2) {
    
     lazy[p].num5+=cnt,tree[p].num5+=cnt, tree[p].maxx=max(tree[p].maxx,tree[p].num5); }
			if(i==3) {
    
     lazy[p].num7+=cnt,tree[p].num7+=cnt, tree[p].maxx=max(tree[p].maxx,tree[p].num7); }
		}
		return ;
	}
	pushdown(p);
	int mid=l+(r-l)/2;
	if(ml<=mid) multi(p*2, l, mid, ml, mr, v);
	if(mr>mid) multi(p*2+1, mid+1, r, ml, mr, v);
	pushup(p);
}

int query_mul(int p,int l,int r,int ql,int qr)
{
    
    
	if(ql<=l && qr>=r) return tree[p].maxx;
	int mid=l+(r-l)/2;
	pushdown(p);
	int ans=0;
	if(ql<=mid) ans=max(ans,query_mul(p*2, l, mid, ql, qr));
	if(qr>mid) ans=max(ans,query_mul(p*2+1, mid+1, r, ql, qr));
	tree[p].maxx=max(tree[p*2].maxx,tree[p*2+1].maxx);
	return ans;
}

int main()
{
    
    
	scanf("%d%d",&n,&q);
	build(1, 1, n);
	while(q--)
	{
    
    
		char s[15];
		scanf("%s",s);
		if(s[1]=='U')
		{
    
    
			int l,r,v; scanf("%d%d%d",&l,&r,&v);
			multi(1, 1, n, l, r, v);
		}
		else
		{
    
    
			int l,r; scanf("%d%d",&l,&r);
			printf("ANSWER %d\n",query_mul(1, 1, n, l, r));
		}
	}
}
//5 100
//MULTIPLY 2 3 8
//MULTIPLY 1 4 8
//m 1 5

建立4棵线段树

#include<iostream>
#include <sstream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
//extern "C"{void *__dso_handle=0;}
typedef long long ll;
typedef long double ld;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define lowbit(x) x&-x
//#define int long long

const double PI=acos(-1.0);
const double eps=1e-6;
const ll mod=1e9+7;
const ll inf=1e18;
const int maxn=1e5+10;
const int maxm=100+10;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

ll num2[maxn<<2],num3[maxn<<2],num5[maxn<<2],num7[maxn<<2];
ll add2[maxn<<2],add3[maxn<<2],add5[maxn<<2],add7[maxn<<2];

char s[15];
int prime[4]={
    
    2,3,5,7};
void pushup(int p)
{
    
    
	num2[p]=max(num2[p*2],num2[p*2+1]);
	num3[p]=max(num3[p*2],num3[p*2+1]);
	num5[p]=max(num5[p*2],num5[p*2+1]);
	num7[p]=max(num7[p*2],num7[p*2+1]);
}
void build(int p,int l,int r)
{
    
    
	if(l==r) {
    
     num2[l]=num3[l]=num5[l]=num7[l]=0; return ;}
	int mid=(l+r)/2;
	build(p*2, l, mid);
	build(p*2+1, mid+1, r);
	pushup(p);
}
void pushdown(int p)
{
    
    
	add2[p*2]+=add2[p]; add2[p*2+1]+=add2[p];
	num2[p*2]+=add2[p]; num2[p*2+1]+=add2[p];
	add3[p*2]+=add3[p]; add3[p*2+1]+=add3[p];
	num3[p*2]+=add3[p]; num3[p*2+1]+=add3[p];
	add5[p*2]+=add5[p]; add5[p*2+1]+=add5[p];
	num5[p*2]+=add5[p]; num5[p*2+1]+=add5[p];
	add7[p*2]+=add7[p]; add7[p*2+1]+=add7[p];
	num7[p*2]+=add7[p]; num7[p*2+1]+=add7[p];
	add2[p]=add3[p]=add5[p]=add7[p]=0;
}
void add(int p,int l,int r,int addl,int addr,int v)
{
    
    
	if(addl<=l && addr>=r) {
    
    
		for(int i=0;i<4;i++)
		{
    
    
			int cnt=0;
			if(v%prime[i]==0)
			{
    
    
				while(v%prime[i]==0){
    
     cnt++; v/=prime[i];}
			}
			if(i==0) {
    
     num2[p]+=cnt; add2[p]+=cnt;}
			if(i==1) {
    
     num3[p]+=cnt; add3[p]+=cnt;}
			if(i==2) {
    
     num5[p]+=cnt; add5[p]+=cnt;}
			if(i==3) {
    
     num7[p]+=cnt; add7[p]+=cnt;}
		}
		return ;
	}
	pushdown(p);
	int mid=(l+r)>>1;
	if(addl<=mid) add(p*2, l, mid, addl, addr, v);
	if(addr>mid) add(p*2+1, mid+1, r, addl, addr, v);
	pushup(p);
}

ll query(int p,int l,int r,int ql,int qr)
{
    
    
	if(ql<=l && qr>=r) {
    
     return max(num2[p],max(num3[p],max(num5[p],num7[p]))); }
	pushdown(p);
	int mid=(l+r)>>1;
	ll maxx=-1;
	if(ql<=mid) maxx=max(maxx, query(p*2, l, mid, ql, qr));
	if(qr>mid) maxx=max(maxx, query(p*2+1, mid+1, r, ql, qr));
	pushup(p);
	return maxx;
}

int main()
{
    
    
	int n,q;
	scanf("%d%d",&n,&q);
	build(1, 1, n);
	while(q--)
	{
    
    
		scanf("%s",s);
		if(s[1]=='U')
		{
    
    
			int l,r,v;
			scanf("%d%d%d",&l,&r,&v);
			add(1, 1, n, l, r, v);
		}
		else
		{
    
    
			int l,r; scanf("%d%d",&l,&r);
			printf("ANSWER %lld\n",query(1, 1, n, l, r));
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_44235989/article/details/108257767
今日推荐