ST+线段树,WA求调
查看原帖
ST+线段树,WA求调
120438
Lacrymabre楼主2021/10/1 13:44

rt,WA求调

  • 如果区间最小值=区间gcd,ans=r-l+1-最小值的数量

  • 用线段树维护区间最小值和她的数量,ST表维护区间gcd(指最大公约数)

  • st-gcd没有挂,放板子题里测过了

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>

#define ll long long
#define db double
#define MAX 0x7fffffff
#define init inline int
#define INF 0X3fffffff
#define N 400001>>1

using namespace std;

inline long long read()
{
    ll f=1,s=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
    return s*f;
}

ll n,a[100001],m,x,y;
ll f[100001][20],lg[100001];

struct node{
	ll num,min;
}s[100001];

node pushup(node l,node r){
	node t;
	t.min=min(l.min,r.min);
	t.num=(l.min==t.min?l.num:0)+(r.min==t.min?r.num:0);
	return t;
}

void build(ll k,ll l,ll r){
//	cout<<k<<" "<<l<<" "<<r<<endl;
	if(l==r) {s[k].min=a[l],s[k].num=1;return;}
	ll mid=l+r>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	s[k]=pushup(s[k<<1],s[k<<1|1]);
}

node query(ll k,ll l,ll r,ll x,ll y){
	if(l>y||x>r) return (node){0,0};
	if(x<=l&&r<=y) return s[k];
	ll mid=l+r>>1;
	return pushup(query(k<<1,l,mid,x,y),query(k<<1|1,mid+1,r,x,y));
}

ll gcd(ll x,ll y){
	if(!y) return x;
	return gcd(y,x%y);
}

void ST(){
	for(int j=1;j<=lg[n]+5;j++)
		for(int i=1;i+(1<<j)-1<=n;i++)
			f[i][j]=gcd(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}

ll sgcd(ll x,ll y){
	ll s=lg[y-x+1];
	return gcd(f[x][s],f[y-(1<<s)+1][s]);
}

int main(){
	n=read();lg[0]=-1;
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=1;i<=n;i++){
		f[i][0]=a[i];
		lg[i]=lg[i>>1]+1;
	}
	ST();build(1,1,n);
	m=read();
	while(m-->0){
		x=read();y=read();
		node q=query(1,1,n,x,y);
		ll GCD=sgcd(x,y);
		cout<<y-x+1-(q.min==GCD?q.num:0)<<endl;
	}
	return 0;
}
2021/10/1 13:44
加载中...