zoukankan      html  css  js  c++  java
  • LCIS

    ### Description

      给你一个长度为(n)的整数序列,你可以进行的操作是(rev(l,r))表示花费(r-l+1)的代价将([l,r])区间内的数字翻转,现在要求在(4*10^6)的代价内最大化最终序列的最长上升子序列长度,输出任意一种构造方案

    ​  数据范围:(n<=32000)(0<=)序列中的数字(<=32000)

      

    Solution

      比较直白的想法就是你如果把整个序列排个序自然就满足LIS条件了,那么现在考虑构造一种满足代价要求的方案

      这里有一种很妙的想法,考虑一个类似快排的处理方式:首先离散化(注意每个数都给一个不同的新值)然后我们分治来做,对于当前区间,我们将该区间的离散化后的中位数作为一个标准值,然后剩下来的数可以分为两类,小于标准值的和大于标准值的,我们将小于标准值的全部丢到(mid)前面,将大于标准值的全部丢到(mid)后面,递归处理完之后前半部分也满足靠后的是大于标准值的,后半部分靠前的是小于标准值的(如果有的话),那么这个时候我们就直接找到前后分界的两个位置然后(rev)一下就可以完成大于标准值和小于标准值两类数的分离,然后我们再用同样的方式处理([l,mid-1])([mid+1,r])即可

      至于贡献的话。。好像01序列排序的交换次数(只能交换相邻位置)是有保障的,然后我们在处理的时候两类数的分离其实就是(01)分离,所以可以保证到总代价不超

      

      代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=32010;
    int a[N],rec[N*14][2],tmp[N];
    int n,m,ans,val;
    void rev(int l,int r){
    	if (l>=r) return;
    	rec[++ans][0]=l; rec[ans][1]=r;
    	reverse(a+l,a+1+r);
    }
    void solve1(int l,int r){
    	if (l>=r) return;
    	int mid=l+r>>1,L,R;
    	solve1(l,mid);
    	solve1(mid+1,r);
    	L=r; R=l;
    	for (int i=l;i<=r;++i)
    		if (a[i]>=val){L=i; break;}
    	for (int i=r;i>=l;--i)
    		if (a[i]<=val){R=i; break;}
    	rev(L,R);
    }
    void solve(int l,int r){
    	if (l>=r) return;
    	int mid=l+r>>1,L,R;
    	for (int i=l;i<=r;++i) tmp[i]=a[i];
    	sort(tmp+l,tmp+1+r);
    	val=tmp[mid];
    	for (int i=l;i<=r;++i){
    		if (a[i]==val){
    			rev(min(i,mid),max(i,mid));
    			break;
    		}
    	}
    	solve1(l,mid-1);
    	solve1(mid+1,r);
    	L=R=mid;
    	for (int i=l;i<=r;++i)
    		if (a[i]>=val){L=i; break;}
    	for (int i=r;i>=l;--i)
    		if (a[i]<=val){R=i; break;}
    	rev(L,R);
    	solve(l,mid-1);
    	solve(mid+1,r);
    }
    bool cmp(int x,int y){return a[x]<a[y];}
    void prework(){
    	for (int i=1;i<=n;++i) tmp[i]=i;
    	sort(tmp+1,tmp+1+n,cmp);
    	for (int i=1;i<=n;++i) a[tmp[i]]=i;
    }
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	scanf("%d",&n);
    	for (int i=1;i<=n;++i) scanf("%d",a+i);
    	prework();
    	solve(1,n);
    	printf("%d
    ",ans);
    	for (int i=1;i<=ans;++i) printf("%d %d
    ",rec[i][0],rec[i][1]);
    }
    
  • 相关阅读:
    6大开源SIEM工具,安全信息和事件管理的“利器”
    数据库为何需要安全审计系统
    WEB漏洞扫描的开源工具
    12种开源Web安全扫描程序
    开源框架openresty+nginx 实现web应用防火墙(WAF)
    锦衣盾:开源WEB应用防火墙介绍
    20步打造最安全的Nginx Web服务器
    MySQL数据库审计系统
    数据库(分库分表)中间件对比
    Mysql调优基础、Mysql问题排查、Mysql优化、与hikari数据库连接池配合
  • 原文地址:https://www.cnblogs.com/yoyoball/p/10040388.html
Copyright © 2011-2022 走看看