zoukankan      html  css  js  c++  java
  • 福建省队集训 20180711

    福建省队集训 20180711

    sequence

    没有这个单调不降的条件就是个傻逼斜率优化,不过这样的题也不会出现在省选题里...

    其实就是把一维的条件升级成二维,cdq分治应该可以做,不过n是1e6

    既然没有1e5的部分分这应该就是正解...吧?

    然后这里的斜率优化是 >和递减查询,维护上凸壳和单调队列。

    没有大样例差差差差评

    注意要单独归并然后存起来,因为递归顺序不一样,而且用vector会T

    题解复杂度还真是nlog,なんだよ、結構当たんじゃねぇか

    #include<bits/stdc++.h>
    #define int ll 
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #define ll long long
    #define FOR(i,a,b) for(register int i=(a);i<=(b);++i) 
    using namespace std;
    inline int read(){
    	int x=0,pos=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    	return pos?x:-x;
    } 
    const int N = 2000201;
    int n;
    ll a[N],top;
    int q[N],id[N];
    ll f[N];
    int cmp(int aa,int bb){
    	return a[aa]==a[bb]?aa<bb:a[aa]<a[bb];
    }
    #define pii pair<int,int>
    #define pb push_back
    #define fi first
    #define se second
    #define mp make_pair
    int vec[26][N]; 
    inline double Y(int i){
    	return 1.0*f[i]-1.0*(i*i+i)/2.0;
    } 
    inline double slope(int i,int j){
    	return (Y(i)-Y(j))/(1.0*(i-j));
    }
    ll calc(int now,int pre){
    	return f[pre]-1ll*(now-pre-1)*(now-pre)/2ll+a[now];
    } 
    inline void solve(int dep,int l,int r){
    	if(l==r) return void();
    	int mid=(l+r)>>1;
    	solve(dep+1,l,mid);
    	top=0;
    /*	FOR(i,l,mid){
    		int now=id[i];
    		while(top>1&&slope(q[top-1],q[top])<slope(q[top],i)) top--;
    		q[++top]=now;
    	}*/
    	int h=1;
    	FOR(i,l,r){
    		int now=vec[dep][i];
    		if(now<=mid){
    			now=id[now];
    			while(top>h&&slope(q[top-1],q[top])<slope(q[top],now)) top--;
    			q[++top]=now;
    		}else{
    			now=id[now];
    			while(h<top&&slope(q[h],q[h+1])>=-now) h++;
    			if(h<=top) f[now]=max(f[now],calc(now,q[h]));
    		}
    	}
    	solve(dep+1,mid+1,r);
    }
    void merge(int dep,int l,int r){
    	if(l==r) return vec[dep][l]=l,void();
    	int mid=(l+r)>>1;
    	merge(dep+1,l,mid);merge(dep+1,mid+1,r);int tl=l,tr=mid+1;
    	FOR(i,l,r) vec[dep][i]=(tl<=mid&&(id[vec[dep+1][tl]]<id[vec[dep+1][tr]]||tr>r))?vec[dep+1][tl++]:vec[dep+1][tr++];
    }
    int lnk[N];
    signed main(){
    	freopen("sequence.in","r",stdin);
    	freopen("sequence.out","w",stdout);
    	n=read();
    	FOR(i,1,n){
    		a[i]=read();
    		id[i]=i;
    		f[i]=-1e18;	
    	}
    	sort(id+1,id+n+1,cmp);
    	merge(1,0,n);
    	solve(1,0,n);
    	ll ans=-1e18;
    	FOR(i,0,n){
    		ans=max(ans,f[i]-1ll*(n-i)*(n-i+1)/2ll);
    	}
    	printf("%lld",ans);
    	return 0;
    }
    

    rope

    只想到枚举两种颜色然后全部先染色...
    假设绳子上只有两种颜色,那么能折到长度为 2 当且仅当除了头尾以外,每 个极长颜色相同段长度都为偶数。

    也就是说,除了第一段以外,每一段的开头的 下标是同奇偶的。

    那么对于一种颜色 a,我们先枚举奇偶,再枚举另一种颜色 b。我们首先要 将所有其它颜色染成 a 或 b,代价为 n-x[a]-x[b] (x[i]表示 i 的个数),接着如果某 个位置奇偶性不对并且恰好是 a 和 b 相邻,那么需要额外 1 点代价。

    那么我们可以不用枚举 b,只要枚举 a 的每一段,将某个颜色的代价+1,最 后查询最小值,再还原即可。

    时间复杂度 O(n)

  • 相关阅读:
    如何向Android模拟器打电话发短信
    APK文件安装模拟器和ADB命令的使用
    android的个人代码总结
    android一些基础知识
    android常用的一些属性说明
    新的博客
    用字符进行布尔值判断,踩到的一个小坑
    通过outlook的web邮箱获取指定邮件内容的邮件
    使用win32com接口获取outlook收件箱的内容
    Python 详解命令行解析
  • 原文地址:https://www.cnblogs.com/lcyfrog/p/13066980.html
Copyright © 2011-2022 走看看