省选模拟12

T1

\(f_i\) 表示以 \(i\) 为结尾的答案,然后转移为 \(f_i=\max\limits_{j=1}^{i-1}(f_j+(a_i-a_j)^2+c)\)

这样会有不合法的情况无法转移,就是两个数之间有比他俩都大的值

但是这样的值一定会比从最大值转移要劣,所以直接斜率做一下就行

Code
#include<bits/stdc++.h>
#define int long long
#define lson rt<<1
#define rson rt<<1|1
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,C,ans;
int a[1000010],f[1000010];
inline int sq(int x){return x*x;}
struct node{
	int k,b;
	inline int calc(int x){return k*x+b;}
}st[1000010*4];
inline bool cover(node a,node b,int x){return b.calc(x)>=a.calc(x);}
void build(int rt,int l,int r){
	st[rt].k=0,st[rt].b=-inf;
	if(l==r) return ;
	int mid=(l+r)>>1;
	build(lson,l,mid);
	build(rson,mid+1,r);
}
void ins(int rt,int l,int r,node k){
	if(cover(st[rt],k,l)&&cover(st[rt],k,r)) return st[rt]=k,void();
	if(l==r) return ;
	int mid=(l+r)>>1;
	if(cover(st[rt],k,mid)) swap(st[rt],k);
	if(cover(st[rt],k,l)) ins(lson,l,mid,k);
	if(cover(st[rt],k,r)) ins(rson,mid+1,r,k);
}
int query(int rt,int l,int r,int pos){
	if(l==r) return st[rt].calc(pos);
	int mid=(l+r)>>1,res=st[rt].calc(pos);
	if(pos<=mid) res=max(res,query(lson,l,mid,pos));
	else res=max(res,query(rson,mid+1,r,pos));
	return res;
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("array.in","r",stdin);
	freopen("array.out","w",stdout);
	n=read(),C=read();
	for(int i=1;i<=n;i++) a[i]=read();
	build(1,1,1000000);
	ins(1,1,1000000,(node){-2*a[1],f[1]+a[1]*a[1]});
	for(int i=2;i<=n;i++){
		f[i]=query(1,1,1000000,a[i])+C+a[i]*a[i];
		ins(1,1,1000000,(node){-2*a[i],f[i]+a[i]*a[i]});
	}
	printf("%lld\n",f[n]);
	return 0;
}

T2

先询问出全局的最大差值,然后二分一个位置找到任意一个极值的位置

因为每个数都不一样,于是与极值作差的结果也都不一样

再按二进制位拆分,每个差值都会在是二进制下是 \(1\) 的那一位出现一次

于是就能找出每个位置与极值的差,然后再找出最大的那个位置

询问一下,看看一开始的值是最大值还是最小值然后就能知道出所有数的值了

Code
#include "difference.h"
#include<bits/stdc++.h>
using namespace std;
namespace TTT{
void find(int n, int M1, int M2){
	int pos,cpos,l,r,mx=-1,v,vc;
	vector<int>vec,s,c,anss;
	map<int,int>mp[20],t;
	vec.resize(n);c.resize(n);anss.resize(n);
	for(int i=0;i<n;i++) vec[i]=i;
	s=qry2(vec);for(auto L:s) mx=max(mx,L);
	l=0,r=n-1;
	while(l<=r){
		int mid=(l+r)>>1,tmx=-1;
		vec.resize(mid+1);for(int i=0;i<=mid;i++) vec[i]=i;
		s=qry2(vec);for(auto L:s) tmx=max(tmx,L);
		if(tmx==mx) r=mid-1,pos=mid;
		else l=mid+1;
	}
	for(int i=0;(1<<i)<=n;i++){
		pos+1>>i&1;
		vec.clear();
		for(int j=1;j<=n;j++) if((j>>i)&1) if(j-1!=pos) vec.emplace_back(j-1);
		s=qry2(vec);for(auto L:s) mp[i][L]--;
		vec.clear();
		for(int j=1;j<=n;j++) if((j>>i)&1) if(j-1!=pos) vec.emplace_back(j-1);
		vec.emplace_back(pos);
		s=qry2(vec);for(auto L:s) mp[i][L]++;
	}
	for(int i=0,sum;i<n;i++) if(i!=pos){
		t.clear();sum=0;
		for(int j=0;(1<<j)<=n;j++) if(((i+1)>>j)&1){
			sum++;
			for(auto L:mp[j]) if(L.second!=0) t[L.first]++;
		}else for(auto L:mp[j]) if(L.second!=0) t[L.first]+=1000;
		for(auto L:t) if(L.second==sum) c[i]=L.first;
	}
	for(int i=0,tmx=-1;i<n;i++){tmx=max(tmx,c[i]);if(tmx==c[i]) cpos=i;}
	v=qry1(pos);vc=qry1(cpos);
	if(v<vc) for(int i=0;i<n;i++) anss[i]=c[i]+v;
	else for(int i=0;i<n;i++) anss[i]=v-c[i];
	return answer(anss),void();
}}
void find(int n, int M1, int M2){TTT::find(n,M1,M2);}

T3

咕咕咕

posted @ 2022-02-09 07:27  Max_QAQ  阅读(94)  评论(2编辑  收藏  举报