• 4418. Prime的把妹计划


    题目描述


    N,Q<=5e4

    题解

    基础线段树

    先算al<=ar的,之后取反再算一次

    设L[i]表示往左第一个大于当前的位置+1,R[i]是往右小于的-1

    那么区间[l,r]满足条件当且仅当R[l]>=r且L[r]<=l

    枚举右端点,在x处维护[x,x~r]的最大值,考虑r-1->r的变化

    加入的区间[x,r]需要满足R[x]>=r,L[r]<=x,即对满足R[x]>=r的x∈[L[r],r]的更新

    按照R[x]排序单调单点删R[x]<r的,维护区间最小值和答案,询问直接查[L,R]

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define inf 2147483647
    #define min(a,b) (a<b?a:b)
    #define max(a,b) (a>b?a:b)
    #define ll long long
    //#define file
    using namespace std;
    
    struct type{int l,r,id;} q[50001];
    struct Type{int x,id;} b[50001];
    int tr[200001][2],Tr[200001],a[50001],L[50001],R[50001],d[50001],ans[50001],h,t,n,i,j,k,l,Q,Find;
    bool Cmp(Type a,Type b) {return a.x<b.x;}
    bool cmp(type a,type b) {return a.r<b.r;}
    
    void mt(int t,int l,int r)
    {
    	int mid=(l+r)/2;
    	Tr[t]=tr[t][0]=tr[t][1]=0;
    	if (l==r) {tr[t][1]=l;return;}
    	
    	mt(t*2,l,mid);
    	mt(t*2+1,mid+1,r);
    	tr[t][1]=min(tr[t*2][1],tr[t*2+1][1]);
    }
    void down(int t,int len)
    {
    	if (Tr[t])
    	{
    		if (len>1)
    		Tr[t*2]=Tr[t],Tr[t*2+1]=Tr[t];
    		tr[t][0]=max(tr[t][0],Tr[t]-tr[t][1]+1);
    		Tr[t]=0;
    	}
    }
    void change(int t,int l,int r,int x,int y,int s)
    {
    	int mid=(l+r)/2;
    	down(t,r-l+1);
    	if (x<=l && r<=y) {Tr[t]=s;down(t,r-l+1);return;}
    	down(t*2,mid-l+1);
    	down(t*2+1,r-mid);
    	
    	if (x<=mid) change(t*2,l,mid,x,y,s);
    	if (mid<y) change(t*2+1,mid+1,r,x,y,s);
    	tr[t][0]=max(tr[t*2][0],tr[t*2+1][0]);
    }
    void Change(int t,int l,int r,int x)
    {
    	int mid=(l+r)/2;
    	down(t,r-l+1);
    	if (l==r) {tr[t][1]=inf;return;}
    	down(t*2,mid-l+1);
    	down(t*2+1,r-mid);
    	
    	if (x<=mid) Change(t*2,l,mid,x);
    	else Change(t*2+1,mid+1,r,x);
    	tr[t][1]=min(tr[t*2][1],tr[t*2+1][1]);
    }
    void find(int t,int l,int r,int x,int y)
    {
    	int mid=(l+r)/2;
    	down(t,r-l+1);
    	if (x<=l && r<=y) {Find=max(Find,tr[t][0]);return;}
    	
    	if (x<=mid) find(t*2,l,mid,x,y);
    	if (mid<y) find(t*2+1,mid+1,r,x,y);
    }
    
    void work()
    {
    	t=0;d[0]=0;
    	fo(i,1,n)
    	{
    		while (t && a[d[t]]<=a[i]) --t;
    		L[i]=d[t]+1;
    		d[++t]=i;
    	}
    	t=0;d[0]=n+1;
    	fd(i,n,1)
    	{
    		while (t && a[d[t]]>=a[i]) --t;
    		R[i]=d[t]-1;
    		d[++t]=i;
    	}
    	fo(i,1,n) b[i]={R[i],i};
    	sort(b+1,b+n+1,Cmp);
    	
    	mt(1,1,n),j=1,k=1;
    	fo(i,1,n)
    	{
    		while (j<=n && b[j].x<i) Change(1,1,n,b[j].id),++j;
    		change(1,1,n,L[i],i,i);
    		while (k<=Q && q[k].r==i) Find=0,find(1,1,n,q[k].l,q[k].r),ans[q[k].id]=max(ans[q[k].id],Find),++k;
    	}
    }
    
    int main()
    {
    	#ifdef file
    	freopen("b.in","r",stdin);
    	freopen("a.out","w",stdout);
    	#endif
    	
    	scanf("%d",&n);
    	fo(i,1,n) scanf("%d",&a[i]);
    	scanf("%d",&Q);
    	fo(i,1,Q) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
    	sort(q+1,q+Q+1,cmp);
    	
    	work();
    	fo(i,1,n) a[i]=-a[i];
    	work();
    	
    	fo(i,1,Q) printf("%d
    ",ans[i]);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    053-242
    053-227
    053-671
    053-489
    053-670
    sql
    白纸黑字签字画押,出人命的事
    CSS
    JS
    Eclipse发布地址不同引发的问题
  • 原文地址:https://www.cnblogs.com/gmh77/p/13618860.html
Copyright © 2020-2023  润新知