zoukankan      html  css  js  c++  java
  • [BZOJ4553][HEOI2016/TJOI2016]序列

    传送门

    好像是DP再套个裸的CDQ?
    树套树是不可能写树套树的,这辈子都不可能写树套树的

    对于一个 (i) ,设它最小为 (a_i) ,原数为 (b_i) ,最大为 (c_i)

    (f_i) 表示 (i) 结尾的最长子序列, (f_i=f_j+1)(j) 要满足

    • (j<i)
    • (c_j leq b_i)
    • (b_j leq a_i)

    这不就CDQ套个树状数组就完了嘛QAQ

    具体的话,把 ([L,mid])(c) 排序,([mid+1,r])(b) 排序,然后像求三维偏序一样套个树状数组就行了。
    处理区间的顺序可能要注意下,树状数组的清空也要控制好复杂度。

    然后交了一发就过了0.0

    #include<bits/stdc++.h>
    #define LL long long
    #define fr(i,x,y) for(int i=(x);i<=(y);i++)
    #define rf(i,x,y) for(int i=(x);i>=(y);i--)
    #define frl(i,x,y) for(int i=(x);i<(y);i++)
    using namespace std;
    const int N=100005;
    const int M=N<<1;
    int n,m,a[N],b[N],c[N];
    int f[N];
    int mx=100000;
    int num[N],t[N];
    
    void read(int &x){
    	char ch=getchar();x=0;
    	for(;ch<'0'||ch>'9';ch=getchar());
    	for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
    }
    
    void chkmin(int &x,int y){ if (y<x) x=y; }
    void chkmax(int &x,int y){ if (y>x) x=y; }
    
    inline int cmpc(const int &q,const int &w){ return c[q]<c[w]; }
    inline int cmpb(const int &q,const int &w){ return b[q]<b[w]; }
    
    inline void ADD(int x,int v){
    	for(;x<=mx;x+=x&(-x)) chkmax(t[x],v);
    }
    
    inline int QRY(int x){
    	int ans=0;
    	for(;x;x^=x&(-x)) chkmax(ans,t[x]);
    	return ans;
    }
    
    inline void DEL(int x){
    	for(;x<=mx;x+=x&(-x)) t[x]=0;
    }
    
    void solve(int L,int r){
    	if (L==r){
    		chkmax(f[L],1);
    		return;
    	}
    	int mid=(L+r)>>1;
    	solve(L,mid);
    	fr(i,L,r) num[i]=i;
    	sort(num+L,num+mid+1,cmpc);
    	sort(num+mid+1,num+r+1,cmpb);
    	int pp1=L,pp2=mid+1;
    	while(pp1<=mid&&pp2<=r){
    		int p1=num[pp1],p2=num[pp2];
    		if (c[p1]<=b[p2]){
    			ADD(b[p1],f[p1]);
    			pp1++;
    		} else{
    			chkmax(f[p2],QRY(a[p2])+1);
    			pp2++;
    		}
    	}
    	for(;pp2<=r;pp2++) chkmax(f[num[pp2]],QRY(a[num[pp2]])+1);
    	fr(i,L,mid) DEL(b[num[i]]);
    	solve(mid+1,r);
    }
    
    int main(){
    	read(n);read(m);
    	fr(i,1,n) read(a[i]),b[i]=c[i]=a[i];
    	int x,y;
    	fr(i,1,m){
    		read(x);read(y);
    		chkmin(a[x],y);
    		chkmax(c[x],y);
    	}
    	solve(1,n);
    	int ans=0;
    	fr(i,1,n) chkmax(ans,f[i]);
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    造出最好的 CMS 轮子
    搭建开发框架Express,实现Web网站登录验证
    QueryOver<T>
    NVelocity
    .NET 相依性注入
    Unity 3.5
    java socket 的参数选项解读(转)
    换种方式去分页(转)
    上海市居住证办理材料及流程
    java动态代理
  • 原文地址:https://www.cnblogs.com/ymzqwq/p/11278980.html
Copyright © 2011-2022 走看看