[省选模拟]array

这题真是太神了!

考试的时候冲着四十分写了个$O(\frac{N^3logN}{32})$的制杖算法。

然后就狠狠的T掉了。如果没有充分的理解单调性和应用单调性就只有10分的傻逼分拿了。

首先考虑枚举两维,那么随着第二维的递增,第三维必定不上升,搞个指针瞎贪贪就是$O(N^2)$了(而我却SB的硬上了个二分)

然后考虑再优化掉一维,我们把值离散化后求出每个值在A,B,C的第一次出现位置,然后按在A的出现位置递减排序。

那么我们枚举A,这样就只用考虑枚举到的之前的情况了,因为枚举到的后面已经被覆盖了。

接着考虑如果一个点的B和C都同时小于另一个点,那么这个点显然是没有用的。

这样的话我们先考虑一个脑残点的算法,每次枚举A的时候把剩下的元素按B排序,这样的话每次把B放到单调队列里同时剔除没有用的元素,这样就必定得到一个B不递减,C不递增的单调队列。

而且这个单调队列里和枚举到的点相邻的点的B和C就构成了答案。

那么显然不能按照上面来,太暴力了。我们开一个set来维护单调队列,开一个multiset来维护答案即可。

//array
//by Cydiater
//2017.2.17
#include <iostream>
#include <queue>
#include <map>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <bitset>
#include <set>
#include <vector>
#include <complex>
using namespace std;
#define ll long long
#define up(i,j,n)	for(int i=j;i<=n;i++)
#define down(i,j,n)	for(int i=j;i>=n;i--)
#define cmax(a,b)	a=max(a,b)
#define cmin(a,b)	a=min(a,b)
#define pii		pair<int,int>
#define FILE		"array"
const int MAXN=1e6+5;
const int oo=1e7+5;
inline int read(){
	char ch=getchar();int x=0,f=1;
	while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
	while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
	return x*f;
}
int N,A[MAXN],B[MAXN],C[MAXN],top=0,num[MAXN],ans=oo;
struct Array{
	int a,b,c;
	Array(){a=b=c=oo-1;}
}d[MAXN];
multiset<int>ANS;
set<pii>Q;
namespace solution{
	bool cmp(Array x,Array y){return x.a>y.a;}
	void Insert(pii now){
		set<pii>::iterator i,j,k;
		cout<<(*ANS.begin())<<endl;
		k=Q.lower_bound(now);
		if(k->second>=now.second)return;
		Q.insert(now);i=Q.find(now);j=i;j--;
		ANS.erase(ANS.find(j->first+k->second));
		ANS.insert(now.first+k->second);
		ANS.insert(j->first+now.second);
		//cout<<(*ANS.begin())<<endl;
		while(j->second<=now.second){
			i=j;j--;
			ANS.erase(ANS.find(j->first+i->second));
			ANS.erase(ANS.find(i->first+now.second));
			Q.erase(i);
			ANS.insert(j->first+now.second);
			//cout<<(*ANS.begin())<<endl;
		}
	}
	void Prepare(){
		N=read();
		up(i,1,N)num[++top]=A[i]=read();
		up(i,1,N)num[++top]=B[i]=read();
		up(i,1,N)num[++top]=C[i]=read();
		sort(num+1,num+top+1);
		top=unique(num+1,num+top+1)-(num+1);
		up(i,1,N)A[i]=lower_bound(num+1,num+top+1,A[i])-num;
		up(i,1,N)B[i]=lower_bound(num+1,num+top+1,B[i])-num;
		up(i,1,N)C[i]=lower_bound(num+1,num+top+1,C[i])-num;
		down(i,N,1)d[A[i]].a=i;
		down(i,N,1)d[B[i]].b=i;
		down(i,N,1)d[C[i]].c=i;
		sort(d+1,d+top+1,cmp);
	}
	void Solve(){
		Q.insert(make_pair(0,oo));
		Q.insert(make_pair(oo,0));
		ANS.insert(0);
		cmin(ans,d[1].a);
		d[top+1].a=0;
		up(i,1,top){
			Insert(make_pair(d[i].b,d[i].c));
			//cout<<d[i+1].a<<‘ ‘<<(*ANS.begin())<<endl;
			cmin(ans,d[i+1].a+(*ANS.begin()));
		}
		cout<<ans<<endl;
	}
}
int main(){
	freopen(FILE".in","r",stdin);
	//freopen(FILE".out","w",stdout);
	using namespace solution;
	Prepare();
	Solve();
	return 0;
}
时间: 2024-08-03 03:09:19

[省选模拟]array的相关文章

省选模拟(61~65)

省选模拟61 1.GTM \(BIT\) 把所有点按照下标排序后,考虑消灭一个点会给多少个点消灭掉 发现左边速度比它大的和右边速度比它小的都能够通过接触它消灭 继续分情况,考虑左边速度比它小的一些点 如果速度比右边速度的最小值要大的话就可以通过接触右边的点消灭 同理对于右边速度比它大的点只要比左边最大值小就照样可以消灭掉 所以每个点能够消灭的,是速度一段区间内的点\([min,max]\) 然后就是线段覆盖问题了 2.字符串游戏 ? 考虑已经知道答案是多少了,然后就是有一个\(ans*n\)的网

省选模拟(66~70)

省选模拟66 1.有限空间跳跃理论 \(FWT\) 给定一个无向图,要求给每条边定向后成为有向无环图,求方案 考虑那个\(dp\) \[dp[S]=\sum_{W\in S}(-1)^{|W|-1}dp[S-W] \] 发现就是一个子集卷积的形式,所以开第二维再卷积就好了 省选模拟67 1.链 模拟 发现如果度数都小于3就可以根据有无环出答案 否则假如第一个度数等于3的点为\(x\),那么为了使\(x\)最后度数小于3,最终消掉的点就只能是\(x\)或它相邻的3个点这四种选择 所以把去掉这4个点

自学前端开发:模拟Array功能 不是扩展子类

function MyArray(){};//创建模拟数组功能的构造函数 MyArray.prototype.length=0;//解决IE下使用扩展子类 数组length的bug (function(){ var methods=['push','pop','shift','unshift','slice','splice','join']; for(var i=0;i<methods.length;i++){ (function(name){ MyArray.prototype[name]=

2018.3.10 省选模拟赛

从这里开始 概况 Problem A 三元组 Problem B 攻略 Problem C 迂回 概况 这是省选T1合集?还是欢乐AK赛? 全班一半以上的人三道题都会做qwq. Doggu还剩一小时时以为自己AK了,然后玩了一小时.虽然最终被卡了20分的常数. ZJC 1个半小时AK?Excuse me? 我这条大咸鱼到最后10分钟才敲完了T1,然后发现线段树要T掉. 发自内心鄙视垃圾出题人卡常数,本来的欢乐AK变成280. 教练给我们考4个小时的试,题面上也这么写的,看题解,woc,考试时间3

[考试反思]0113省选模拟6:过载

真累啊...离上次放假也挺久,离下次放假也挺久,离上次放出去玩也挺久,离下次放出去玩还不知道有多久... 好累啊...大脑基本成天在挂机了.什么也不想干了... 持续状态不佳.但是今天运气好,所以考试排名看起来还可以. T1没认真读题也没看数据范围,以为是送分题,17分钟写完交了...然后我就把分送出去了 像个弱智一样...但是现在的精神状态的确不太能支持好好做题 幸亏T2是个比较简单的SAM+dp,思维量不大,脑子宕机的时候也能写一写. (归功于当时给大家讲课时稍微有一点理解,要是其它的板子我

[考试反思]0114省选模拟7:迷离

这次考得相对不错,但是没什么水准. 只不过记得T1这道原题而已.虽说我忘了怎么做,而且数据范围不一样...差不多是从头想的. 但是并没有AC,像个弱智一样,有两个细节写的完全不对还有80分运气也是真好. 其实挂了不止两个细节...以为是原题于是上来就写20分钟写完,然后过一会出一个锅... 然后看T2,感觉$O(nk^2)$也许差不多?常数很大...但也不会别的.挺好想但是不是很好写. 于是乎强烈谴责cbx没素质暴力水题考后还不改正解的无脸行径 于是就开始写,写了一个半小时. 看T3,绝对大神题

省选模拟二十九 题解

T1 考场上只想到了枚举拆三元环,拿到60pts 发现其实有一个性质没有用到: 保证将这  个点移除后,剩余的图将不存在环. 假设黑点为没有被钦定的点,白点反之 三白的情况无解 那么一个三元环只能由二黑一白/二白一黑组成, 后者已经固定了,直接选,而前者并不是很好处理 首先对黑白点分别求出子图的Top序(由于是竞赛图,所以Top序是严格的) 接着对于每个黑点处理出它到白点的一个序列(设W->B=1,B->W=0) 把序列按照白点Top序排序 考虑什么样的x才是不合法的 当且仅当存在一个0在1的

省选模拟三十四 题解

T1 假如max(a)<0的话直接把所有的a排个序贪心选择大的尽量多 现在考虑一个正的ai对后面的影响 维护一个大根堆,a<0就往里添,a>=0就去抵消堆顶元素 这样新序列(堆里的元素)就可以像刚才那样做了 T2 先把点按权值从大到小排序 然后枚举那个点可以选也可以不选 前面的都已经选了 然后在当前枚举的颜色中优先选择那些到根的路径上权值合法的 更新答案 因为如果要是想往小枚举的话一定要选择完当前颜色 所以把当且颜色全部连到根上后还需要额外的考虑中间小于当且权值的点 就是一个递归模拟 最

省选模拟五十六 题解

T1 异或和为0则先手必败 设\(dp[i][j][k]\)代表考虑到\(i\)选了\(j\)个数(对\(d\)取模)异或和为\(k\)的方案数 假如把\(a\)从大到小排序的话便可以剪枝: 第三维是\(2^b\)(b是满足\(2^b>a[i]\)的第一个数) 复杂度\(O(1e7*d)\) T2 设\(f[i][j][k]\)代表从S走k步到T不经过S,T的方案数 \(g[i][j][k]\)代表从S走k步到T的方案数 \(h[i][j][k]\)代表从S走k步到S不经过T的方案数 \(g\)