dtoi4266 exchange

题意:

     给一个长度为n的序列,m次询问,给定区间[a,b],你的任务是从[a,b]中选择一个点,使得从这个点出发走到b的贪心上升子序列最长,输出最长的序列长度。贪心上升子序列指的是遇到一个值比当前队尾的值大就加入队列(不同于最长上升子序列)。

题解:

     先考虑对于a[i],它会影响那些位置的答案。

     显然,对于a[i],会对从(las[i]+1)~i的位置出发的答案造成1的贡献(las[i]为上一个大于等于a[i]的位置)。因为从这些点出发,无论怎么走,都是会走到i的,因此答案会+1。

     由于本题数据较大,因此我们可以离线,按照右端点排序,每次加入一个i,就把(las[i]+1)~i的位置全部+1。求答案只需要找到[a,b]中的最大值即可。用线段树维护即可解决上述操作与查询。

#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
int n,m,a[1500002],ans[1500002],t[1500002],len,c[1500002];
typedef struct{
    int l,r,num;
}P;
typedef struct{
    int Max,f;
}PP;
P p[1500002];
PP xds[6000002];
int read(){
    int f=0;char ch=getchar();
    while(ch<'0' || ch>'9')ch=getchar();
    while(ch>='0' && ch<='9'){f=f*10+ch-48;ch=getchar();}
    return f;
}
bool cmp(P aa,P bb){
    return (aa.r<bb.r);
}
void pushdown(int root){
    if (xds[root].f)
    {
        xds[root*2].Max+=xds[root].f;xds[root*2+1].Max+=xds[root].f;
        xds[root*2].f+=xds[root].f;xds[root*2+1].f+=xds[root].f;
        xds[root].f=0;
    }
}
void gengxin(int root,int begin,int end,int begin2,int end2){
    if (begin>end2 || end<begin2)return;
    if (begin>=begin2 && end<=end2)
    {
        xds[root].Max++;xds[root].f++;
        return;
    }
    int mid=(begin+end)/2;pushdown(root);
    gengxin(root*2,begin,mid,begin2,end2);gengxin(root*2+1,mid+1,end,begin2,end2);
    xds[root].Max=max(xds[root*2].Max,xds[root*2+1].Max);
}
int chaxun(int root,int begin,int end,int begin2,int end2){
    if (begin>end2 || end<begin2)return 0;
    if (begin>=begin2 && end<=end2)return xds[root].Max;
    int mid=(begin+end)/2;pushdown(root);
    return max(chaxun(root*2,begin,mid,begin2,end2),chaxun(root*2+1,mid+1,end,begin2,end2));
}
int main()
{
    n=read();m=read();
    for (int i=1;i<=n;i++)a[i]=read();
    for (int i=1;i<=m;i++)
    {
        p[i].l=read();p[i].r=read();p[i].num=i;
    }
    sort(p+1,p+m+1,cmp);
    int l=1;
    for (int i=1;i<=n;i++)
    {
        while(len && a[t[len]]<a[i])len--;
        gengxin(1,1,n,t[len]+1,i);
        t[++len]=i;
        while(l<=m && p[l].r<=i)
        {
            ans[p[l].num]=chaxun(1,1,n,p[l].l,p[l].r);
            l++;
        }
    }
    for (int i=1;i<=m;i++)printf("%d
",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/1124828077ccj/p/12241830.html