• 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;
    }
  • 相关阅读:
    如何用C语言写一个基于服务器和客户端(TCP)
    如何把C++的源代码改写成C代码?
    可自定义的超链接控件
    一个XP风格的下拉分离按钮
    GroupControl
    带有工具提示和/或位图资源的按钮
    动态更改按钮图像
    一键启用/禁用一组控件
    粘性Snap-to-Center控制
    WinForm ImageButton
  • 原文地址:https://www.cnblogs.com/1124828077ccj/p/12241830.html
Copyright © 2020-2023  润新知