Loading

2024.4.5 RMQ补题

P2048 [NOI2010] 超级钢琴

前缀和处理连续子段的和弦,然后 rmq 求最大值

运用堆存储最优答案

每次取出堆头统计一次后,除掉统计点再分成两段加入即可,共 k 次

#include<bits/stdc++.h>
#define maxn 500010
#define INF 0x3f3f3f3f
#define int long long

using namespace std;

int n,k,l,r,ans;
int f[maxn][30],sum[maxn];
struct node{
  int fr,to,l,r;
  bool operator < (const node &b) const{
    return sum[to]-sum[fr-1]<sum[b.to]-sum[b.fr-1];
  }
};

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

int query(int l,int r){
  int k=log2(r-l+1);
  int x=f[l][k],y=f[r-(1<<k)+1][k];
  return sum[x]>sum[y]?x:y;
}

signed main(){
//  memset(f,128,sizeof f);
  n=read();k=read();l=read();r=read();
  for(int i=1;i<=n;i++) 
    sum[i]=sum[i-1]+read(),f[i][0]=i;
  int lenth=log2(n);
  for(int j=1;j<=lenth;j++)
    for(int i=1;i+(1<<j)-1<=n;i++){
      int x=f[i][j-1],y=f[i+(1<<(j-1))][j-1];
      f[i][j]=(sum[x]>sum[y])?x:y;
    }
  priority_queue<node> q;
  for(int i=1;i<=n;i++)
    if(i+l-1<=n) q.push((node){i,query(i+l-1,min(n,i+r-1)),i+l-1,min(n,i+r-1)});
  for(int i=1;i<=k;i++){
    node u=q.top();q.pop();
    ans+=sum[u.to]-sum[u.fr-1];
    if(u.l!=u.to) q.push((node){u.fr,query(u.l,u.to-1),u.l,u.to-1});
    if(u.r!=u.to) q.push((node){u.fr,query(u.to+1,u.r),u.to+1,u.r}); 
  }
  printf("%lld\n",ans);
  return 0;
}

UVA11235 Frequent values

非降序数列,因此可以直接统计数字的值和个数,即数字段的长度

再记录每一段的左右和每个点所在的段数

查 (l,r) 就可以查中间的若干段和两边的残段,其中中间用 st 表

#include <bits/stdc++.h>
#define maxn 100010
using namespace std;

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

int n,q,le,ri,ans;
int a[maxn],num[maxn],l[maxn],r[maxn],d[maxn][30];
vector<int> cnt;

int query(int l,int r){
    int k=log2(r-l+1);
    return max(d[l][k],d[r-(1<<k)+1][k]);
}

int main(){
    while (scanf("%d",&n)){
    	if (!n) break;q=read();
        for (int i=0;i<n;++i) a[i]=read();
        a[n]=a[n-1]+1;int start=-1;
        for (int i=1;i<=n;++i){
            if (i==0||a[i]>a[i-1]){
                if (i>0) {
                    cnt.push_back(i-start);
                    for (int j=start; j<i; ++j) {
                        num[j]=cnt.size()-1;
                        l[j]=start;r[j]=i-1;
                    }
                }
                start=i;
            }
        }
        int _n=cnt.size();
        for (int i=0;i<_n;++i) d[i][0]=cnt[i];
        for (int j=1;(1<<j)<=_n;++j)
            for (int i=0;i+(1<<j)-1<_n;++i) 
                d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
        while (q--){
            le=read()-1;ri=read()-1;
            if (num[le]==num[ri]) ans=ri-le+1; 
			else {
                ans=max(ri-l[ri]+1,r[le]-le+1);
                if(num[le]+1<num[ri])
                    ans=max(ans, query(num[le]+1,num[ri]-1));
            }
            printf("%d\n", ans);
        }
	}
    return 0;
}

UVA11297Census

二维 rmq

再一个方向开个线段树,然后每个点为另一个方向开一个新的线段树

#include <bits/stdc++.h>  
using namespace std;  
  
int n,m,a[501][501],maxn,minn;  
struct node{ int maxv,minv;}p[2001][2001];  

int read(){
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
	return s*w;
}
  
void build2(int mo,int ml,int mr,int o,int l,int r){  
    if(l!=r){  
        int m=(l+r)>>1;  
        build2(mo,ml,mr,o<<1,l,m);  
        build2(mo,ml,mr,(o<<1)+1,m+1,r);  
        p[mo][o].maxv=max(p[mo][o<<1].maxv,p[mo][(o<<1)+1].maxv);  
        p[mo][o].minv=min(p[mo][o<<1].minv,p[mo][(o<<1)+1].minv);  
    }  
    else{  
        if(ml==mr)p[mo][o].maxv=p[mo][o].minv=a[ml][l];  
        else {  
            p[mo][o].maxv=max(p[mo<<1][o].maxv,p[(mo<<1)+1][o].maxv);  
            p[mo][o].minv=min(p[mo<<1][o].minv,p[(mo<<1)+1][o].minv);  
        }  
    }  
}  
  
void build1(int o,int l,int r){  
    if(l!=r){  
        int m=(l+r)>>1;  
        build1(o<<1,l,m);  
        build1((o<<1)+1,m+1,r);  
    }  
    build2(o,l,r,1,1,n);  
}  
  
void query2(int o,int l,int r,int ql,int qr,int mo){  
    if(l>=ql && r<=qr){  
        maxn=max(maxn,p[mo][o].maxv);  
        minn=min(minn,p[mo][o].minv);  
    }  
    else{  
        int m=(l+r)>>1;  
        if(ql<=m)query2(o<<1,l,m,ql,qr,mo);  
        if(qr>m)query2((o<<1)+1,m+1,r,ql,qr,mo);  
    }  
}  
  
void query1(int o,int l,int r,int ql,int qr,int l2,int r2){  
    if(l>=ql && r<=qr){  
        query2(1,1,n,l2,r2,o);  
    }  
    else{  
        int m=(l+r)>>1;  
        if(ql<=m)query1(o<<1,l,m,ql,qr,l2,r2);  
        if(qr>m)query1((o<<1)+1,m+1,r,ql,qr,l2,r2);  
    }  
}  
  
void update2(int o,int l,int r,int q,int val,int mo){  
    if(l==r){  
        if(val==-1){  
            p[mo][o].maxv=max(p[mo<<1][o].maxv,p[(mo<<1)+1][o].maxv);  
            p[mo][o].minv=min(p[mo<<1][o].minv,p[(mo<<1)+1][o].minv);  
            return;  
        }  
        p[mo][o].maxv=p[mo][o].minv=val;  
        return;  
    }  
    int m=(l+r)>>1;  
    if(q<=m)update2(o<<1,l,m,q,val,mo);else update2((o<<1)+1,m+1,r,q,val,mo);  
    p[mo][o].maxv=max(p[mo][o<<1].maxv,p[mo][(o<<1)+1].maxv);  
    p[mo][o].minv=min(p[mo][o<<1].minv,p[mo][(o<<1)+1].minv);  
}  
  
void update1(int o,int l,int r,int qx,int qy,int val){  
    if(l==r) update2(1,1,n,qy,val,o);  
    else {  
        int m=(l+r)>>1;  
        if(qx<=m)update1(o<<1,l,m,qx,qy,val);
		else update1((o<<1)+1,m+1,r,qx,qy,val);  
        update2(1,1,n,qy,-1,o);  
    }  
}  
  
int main()  {  
    n=read(); 
    for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
			a[i][j]=read();  
    build1(1,1,n);m=read();char opt;  
    for(int i=1,x,y,c,xx,yy;i<=m;++i){  
        cin>>opt;
        if(opt=='q'){   
            x=read();y=read();xx=read();yy=read();  
            minn=0x3f3f3f3f;maxn=0;  
            query1(1,1,n,x,xx,y,yy);  
            printf("%d %d\n",maxn,minn);  
        }  
        else {   
            scanf("%d%d%d",&x,&y,&c);  
            update1(1,1,n,x,y,c);  
        }  
    }  
}  
posted @ 2024-04-05 21:54  KnightL  阅读(16)  评论(0编辑  收藏  举报