zoukankan      html  css  js  c++  java
  • [BZOJ]2090: [Poi2010]Monotonicity 2

    题解: LIS的变式版本   我们用两颗线段树和一个数组来维护  dp[i]表示以i结尾的最长满足条件的序列  转移的话  分情况转移  他可以是从 大于 小于 等于三个方向转移过来 然后取max即可 更新的话  已知dp[i]可以推出下一个符号  然后在对应的数据结构中更新即可

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=5e5+10;
    const double eps=1e-8;
    #define ll long long
    using namespace std;
    struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    
    int n,k;
    int a[MAXN];
    vector<int>vec;
    int base;
    
    int maxx1[MAXN<<2],maxx2[MAXN<<2],ans1,dp[MAXN],maxx3[MAXN];
    char str[MAXN];
    void update1(int rt,int l,int r,int t,int k){
        maxx1[rt]=max(maxx1[rt],k);
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(t<=mid)update1(rt<<1,l,mid,t,k);
        else update1(rt<<1|1,mid+1,r,t,k);
    }
    
    void query1(int rt,int l,int r,int ql,int qr){
        if(ql>qr)return ;
        if(ql<=l&&r<=qr){ans1=max(ans1,maxx1[rt]);return ;}
        int mid=(l+r)>>1;
        if(ql<=mid)query1(rt<<1,l,mid,ql,qr);
        if(qr>mid)query1(rt<<1|1,mid+1,r,ql,qr);
    }
    
    void update2(int rt,int l,int r,int t,int k){
        maxx2[rt]=max(maxx2[rt],k);
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(t<=mid)update2(rt<<1,l,mid,t,k);
        else update2(rt<<1|1,mid+1,r,t,k);
    }
    
    void query2(int rt,int l,int r,int ql,int qr){
        if(ql>qr)return ;
        if(ql<=l&&r<=qr){ans1=max(ans1,maxx2[rt]);return ;}
        int mid=(l+r)>>1;
        if(ql<=mid)query2(rt<<1,l,mid,ql,qr);
        if(qr>mid)query2(rt<<1|1,mid+1,r,ql,qr);
    }
    
    int main(){
        n=read();k=read();
        inc(i,1,n)a[i]=read(),vec.pb(a[i]);
        inc(i,1,k)scanf(" %c",&str[i]);
        sort(vec.begin(),vec.end());
        base=unique(vec.begin(),vec.end())-vec.begin();
        inc(i,1,n)a[i]=lower_bound(vec.begin(),vec.begin()+base,a[i])-vec.begin()+1;
        //maxx1 大于  maxx2 小于 maxx3 等于
        inc(i,1,n){
    	dp[i]=maxx3[a[i]]+1;
    	ans1=0;query1(1,1,base,a[i]+1,base);dp[i]=max(dp[i],ans1+1);
    	ans1=0;query2(1,1,base,1,a[i]-1);dp[i]=max(dp[i],ans1+1);
    	if(str[(dp[i]-1)%k+1]=='>')update1(1,1,base,a[i],dp[i]);
    	else if(str[(dp[i]-1)%k+1]=='<')update2(1,1,base,a[i],dp[i]);
    	else maxx3[a[i]]=max(maxx3[a[i]],dp[i]);
        }
        int ans=0;
        inc(i,1,n)ans=max(ans,dp[i]);
        printf("%d
    ",ans);
    }
    

      

    2090: [Poi2010]Monotonicity 2

    Time Limit: 30 Sec  Memory Limit: 259 MB
    Submit: 311  Solved: 167
    [Submit][Status][Discuss]

    Description

    给出N个正整数a[1..N],再给出K个关系符号(>、<或=)s[1..k]。
    选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1)mod K+1]。
    求出L的最大值。

    Input

    第一行两个正整数,分别表示N和K (N, K <= 500,000)。
    第二行给出N个正整数,第i个正整数表示a[i] (a[i] <= 10^6)。
    第三行给出K个空格隔开关系符号(>、<或=),第i个表示s[i]。

    Output

    一个正整数,表示L的最大值。

    Sample Input

    7 3
    2 4 3 1 3 5 3
    < > =

    Sample Output

    6
  • 相关阅读:
    哈利波特买书事件
    闹钟类app构想
    梦断代码(7-尾)
    梦断代码(3-6)
    梦断代码(0-2)
    环形二维数组求最大子矩阵
    数组问题
    电梯考察
    四则运算的三张计划表
    团队开发用户需求调研
  • 原文地址:https://www.cnblogs.com/wang9897/p/10348922.html
Copyright © 2011-2022 走看看