冲刺省选2月8日第十二场

T1

设 \(f_i\) 表示以 \(i\) 结尾的最大答案

发现只考虑当 \(a_i\) 是最大值时的转移也是正确的

即 \(f_i=\max_{j=1}^{i-1} \{ (b_j-b_i)^2+c+f_j \}\)

因为若中间夹着个比 \(a_i,a_j\) 值都大的值的话肯定不会优

然后李超树维护就行

T2

首先,如果知道了序列的最大值 \(mx\),设询问的集合为 \(S\),并且询问 \(S\bigcup {mx}\),就可以知道集合所有元素与最大值的差

先考虑找到最大值,首先全体询问得到极差 \(k\),然后二分前缀得到 \(k\) 第一次出现的位置,即为最大值或最小值,设为 \(x\)

然后设 \(S_i\) 表示第 \(i\) 个二进制位为 \(1\) 的数的集合,询问 \(S_i\) 和 \(S\bigcup {x}\) 得到与 \(x\) 的差

然后就能得到 \(a_i\)与 \(x\) 的差

\(qry1\) 询问差最大的那个数并与 \(x\) 比较,就能确定 \(x\) 是最大还是最小

代码

T1

#include<cstdio>
#include<iostream>
using namespace std;
#define il inline
#define int long long
const int N=1e6+11;
const int inf=1e18;
struct seg_{
	int k,val;seg_(){}
	seg_(int k_,int val_){k=k_,val=val_;}
};
struct tree{bool jd;seg_ x;}tre[N*4];
int n,c;
int a[N];
il int pd(int x){return x*x;}
il int max_(int x,int y){return x>y?x:y;}
int get_ans(seg_ a,int x){return a.k*x+a.val;}
bool check(seg_ a,seg_ b,int x){return get_ans(a,x)<get_ans(b,x);}
il int read(){
	int s=0;char ch=getchar();
	while(ch>'9'||ch<'0')ch=getchar();
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return s;
}
void ins(int i,int l,int r,seg_ x){
	int mid=(l+r)>>1;
	if(!tre[i].jd){tre[i].jd=1;tre[i].x=x;return;}
	if(check(tre[i].x,x,mid))swap(tre[i].x,x);
	if(l==r)return;
	if(check(tre[i].x,x,r))ins(i<<1|1,mid+1,r,x);
	if(check(tre[i].x,x,l))ins(i<<1,l,mid,x);
}
int qry(int i,int l,int r,int x){
	if(!tre[i].jd)return -inf;
	if(l==r)return get_ans(tre[i].x,x);
	int mid=(l+r)>>1;
	int ans=tre[i].jd?get_ans(tre[i].x,x):-inf;
	if(x<=mid) return max_(ans,qry(i<<1,l,mid,x));
	else return max_(ans,qry(i<<1|1,mid+1,r,x));
}
signed main(){
	freopen("array.in","r",stdin),freopen("array.out","w",stdout);
	n=read();c=read();
	for(int i=1;i<=n;++i)a[i]=read();
	ins(1,1,1e6,seg_(-2*a[1],pd(a[1])));
	for(int x,i=2;i<=n;++i){
		x=qry(1,1,1e6,a[i])+pd(a[i])+c;
		if(i==n)cout<<x<<endl;
		ins(1,1,1e6,seg_(-2*a[i],x+pd(a[i])));
	}
}

T2

#include "difference.h"
#include<set>
#include<vector>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
#define il inline
const int N=250+11;
const int M=N*N;
set<int> mrg(set<int> a,set<int> b){
	if(!a.size())return b;
	set<int> x;x.clear();
	for(set<int>::iterator it=a.begin();it!=a.end();++it){
		if(b.find(*it)!=b.end()){
			x.insert(*it);
			b.erase(*it);
		}
	}return x;
}
set<int> pop(set<int> a,set<int> b){
	for(set<int>::iterator it=b.begin();it!=b.end();++it){
		if(a.find(*it)!=a.end())a.erase(*it);
	}return a;
}
void find(int n,int m1,int m2){
	set<int> s[10];
	vector<int> a,b,ans;
	unordered_map<int,int>mp;

	for(int i=0;i<n;++i)a.push_back(i);
	b=qry2(a);sort(b.begin(),b.end());
	int mx_cz=b[b.size()-1];
	int l=1,r=n-1,mid,loc=0;
	while(l<=r){
		mid=(l+r)>>1;a.clear();
		for(int i=0;i<=mid;++i)a.push_back(i);
		b=qry2(a);sort(b.begin(),b.end());
		if(b[b.size()-1]==mx_cz)loc=mid,r=mid-1;
		else l=mid+1;
	}

	for(int i=0;i<8;++i){
		a.clear();
		for(int j=0;j<n;++j){
			if(j==loc)continue;
			if((1<<i)&j)a.push_back(j);
		}b=qry2(a);mp.clear();
		for(int j=0;j<b.size();++j)++mp[b[j]];
		a.push_back(loc);b=qry2(a);
		for(int j=0;j<b.size();++j){
			if(mp[b[j]])--mp[b[j]];
			else s[i].insert(b[j]);
		}
	}//for(int j : s[2])cout<<j<<" fdafd"<<endl;

	int jd=1;int k=0;
	for(int i=0;i<n;++i)ans.push_back(0);
	ans[loc]=qry1(loc);
	for(int x,i=0;i<n;++i){
		s[8].clear();
		if(i==loc)continue;
		for(int j=0;j<8;++j)if((1<<j)&i)s[8]=mrg(s[8],s[j]);
		for(int j=0;j<8;++j)if(!((1<<j)&i))s[8]=pop(s[8],s[j]);
		if(s[8].size())x=*s[8].begin();
		a.clear();a.push_back(i),a.push_back(loc);
		ans[i]=i?x:qry2(a)[0];
		if(ans[i]==mx_cz){
			k=i;ans[i]=qry1(i);
			if(ans[i]>ans[loc])jd=1;
			else jd=-1;
		}
	}
	for(int i=0;i<n;++i){
		if(i==k||i==loc)continue;
		ans[i]=ans[loc]+jd*ans[i];
	}answer(ans);
}
上一篇:ECS训练营笔记第三天


下一篇:Ubuntu 20.04.3 LTS下txt文件乱码问题