• BZOJ4553: [Tjoi2016&Heoi2016]序列


    Description

     佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他。玩具上有一个数列,数列中某些项的值

    可能会变化,但同一个时刻最多只有一个值发生变化。现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你
    ,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可
    。注意:每种变化最多只有一个值发生变化。在样例输入1中,所有的变化是:
    1 2 3
    2 2 3
    1 3 3
    1 1 31 2 4
    选择子序列为原序列,即在任意一种变化中均为不降子序列在样例输入2中,所有的变化是:3 3 33 2 3选择子序列
    为第一个元素和第三个元素,或者第二个元素和第三个元素,均可满足要求

    Input

     输入的第一行有两个正整数n, m,分别表示序列的长度和变化的个数。接下来一行有n个数,表示这个数列原始的

    状态。接下来m行,每行有2个数x, y,表示数列的第x项可以变化成y这个值。1 <= x <= n。所有数字均为正整数
    ,且小于等于100,000

    Output

     输出一个整数,表示对应的答案

    Sample Input

    3 4
    1 2 3
    1 2
    2 3
    2 1
    3 4

    Sample Output

    3
     
    设B[i]表示A[i]能变成的最大值,C[i]表示A[i]能变成的最小值,然后就可以DP了。
    f[i]=max(f[j]|B[j]<=A[i]&&A[j]<=C[i])+1,不难发现是一个三维偏序结构。
    首先我写了个线段树套线段树,然后被精妙地卡内存了。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    const int maxnode=13000010;
    const int inf=1e9;
    int n,m,ans,A[maxn],B[maxn],C[maxn],f[maxn];
    int root[maxn<<2],maxv[maxnode],ls[maxnode],rs[maxnode],ToT;
    void insert(int& o,int l,int r,int p,int val) {
        if(!o) o=++ToT;maxv[o]=max(maxv[o],val);
        if(l==r) return;int mid=l+r>>1;
        if(p<=mid) insert(ls[o],l,mid,p,val);
        else insert(rs[o],mid+1,r,p,val);
    }
    void insert(int o,int l,int r,int x,int y,int val) {
        insert(root[o],1,100000,y,val);if(l==r) return;
        int mid=l+r>>1,lc=o<<1,rc=lc|1;
        if(x<=mid) insert(lc,l,mid,x,y,val);
        else insert(rc,mid+1,r,x,y,val);
    }
    int query(int o,int l,int r,int p) {
        if(!o) return 0;
        if(l==r) return maxv[o];
        int mid=l+r>>1;
        if(p<=mid) return query(ls[o],l,mid,p);
        return max(maxv[ls[o]],query(rs[o],mid+1,r,p));
    }
    int query(int o,int l,int r,int x,int y) {
        if(l==r) return query(root[o],1,100000,y);
        int mid=l+r>>1,lc=o<<1,rc=lc|1;
        if(x<=mid) return query(lc,l,mid,x,y);
        return max(query(root[lc],1,100000,y),query(rc,mid+1,r,x,y));
    }
    int main() {
        n=read();m=read();
        rep(i,1,n) A[i]=B[i]=C[i]=read();
        rep(i,1,m) {
            int x=read(),y=read();
            B[x]=max(B[x],y);
            C[x]=min(C[x],y);
        }
        rep(i,1,n) {
            f[i]=query(1,1,100000,A[i],C[i])+1;
            insert(1,1,100000,B[i],A[i],f[i]);
            ans=max(ans,f[i]);
        }
        printf("%d
    ",ans);
        return 0;
    }
    

    然后写了个kd树,跑得真是慢。。。

    #include<cstdio>
    #include<cctype>
    #include<set>
    #include<cstring>
    #include<algorithm>
    #define L T[o].lc
    #define R T[o].rc
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
    	if(head==tail) {
    		int l=fread(buffer,1,BufferSize,stdin);
    		tail=(head=buffer)+l;
    	}
    	return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    const int inf=1e9;
    int D,n,m,ans,A[maxn],B[maxn],C[maxn],f[maxn];
    struct Node {
    	int x[2],mx[2],mn[2],lc,rc,val,maxv;
    	bool operator < (const Node& ths) const {return x[D]<ths.x[D]||(x[D]==ths.x[D]&&x[D^1]<ths.x[D^1]);}
    }T[maxn],P;
    void maintain(int o) {T[o].maxv=max(T[o].val,max(T[L].maxv,T[R].maxv));}
    void build(int& o,int l,int r,int cur) {
    	int mid=l+r>>1;D=cur;o=mid;nth_element(T+l,T+mid,T+r+1);
    	if(l<mid) build(L,l,mid-1,cur^1);
    	if(mid<r) build(R,mid+1,r,cur^1);
    	rep(c,0,1) {
    		T[o].mn[c]=min(T[o].x[c],min(T[L].mn[c],T[R].mn[c]));
    		T[o].mx[c]=max(T[o].x[c],max(T[L].mx[c],T[R].mx[c]));
    	}
    }
    int query(int o) {
    	if(!o) return 0;
    	if(T[o].mn[0]>P.x[0]||T[o].mn[1]>P.x[1]) return 0;
    	if(T[o].mx[0]<=P.x[0]&&T[o].mx[1]<=P.x[1]) return T[o].maxv;
    	int ans=0;
    	if(T[o].x[0]<=P.x[0]&&T[o].x[1]<=P.x[1]) ans=T[o].val;
    	return max(ans,max(query(L),query(R)));
    }
    void insert(int o,int cur,int val) {
    	if(T[o].x[0]==P.x[0]&&T[o].x[1]==P.x[1]) T[o].val=max(T[o].val,val);
    	else {
    		D=cur;insert(P<T[o]?L:R,cur^1,val);
    	}
    	maintain(o);
    }
    int main() {
    	T[0].mn[0]=T[0].mn[1]=inf;
    	T[0].mx[0]=T[0].mx[1]=-inf;
    	n=read();m=read();int rt=0;
    	rep(i,1,n) A[i]=B[i]=C[i]=read();
    	rep(i,1,m) {
    		int x=read(),y=read();
    		B[x]=max(B[x],y);
    		C[x]=min(C[x],y);
    	}
    	rep(i,1,n) T[i].x[0]=B[i],T[i].x[1]=A[i];
    	build(rt,1,n,0);
    	rep(i,1,n) {
    		P.x[0]=A[i];P.x[1]=C[i];
    		f[i]=query(rt)+1;
    		P.x[0]=B[i];P.x[1]=A[i];
    		insert(rt,0,f[i]);
    		ans=max(ans,f[i]);
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    UML类图和用例图
    设计模式基本原则
    c# 协变和逆变
    git本地忽略
    计算器科学概论-数据操控
    计算机科学概论-数据存储
    docker部署gitlab-ce
    sqlserver2008R2 本地不能用localhost连接
    Redis常用命令
    C# 值类型和引用类型的区别
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5506325.html
Copyright © 2020-2023  润新知