[考试总结]noip模拟59

这个新机房首模拟就做的很烂。。。

不过话说新机房真的强!!!!

656666.png

这个东西是真的顶。

不废话了。。

柱状图

一个退火就能搞定。

只不过难度在如何对于一个最大高度然后进行 \(\mathcal O(n)\)\(check\)

这个就是我们把这个东西‘‘填平’’就行。

然后我们对于选择 \(check\) 里面的参数使用退火就能过掉了。




#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(a) FILE *FI = freopen(#a".in","r",stdin); FI = freopen(#a".out","w",stdout);
    #define debug cout<<"debug"<<endl
    #define jb(x) cout<<#x" = "<<x<<endl
    #define sb(x) cout<<#x" = "<<x<<' '
    #define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
	char buf[1<<20],*p1 = buf,*p2 = buf;
    class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
    {
        s = 0; register bool f = 0; register char ch = gc();
        while(!isdigit(ch)) f |= ch == '-',ch = gc();
        while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
    }}io;
}
#define int long long
using namespace xin_io; static const int maxn = 1e6+10,llinf = 1e18+10;
//auto abs = [](int x) -> int{return x < 0 ? -x : x;};
namespace xin
{
	inline int abs(int x){return x < 0 ? -x : x;}
	int n,mid,ans = llinf*2;
	int a[maxn],temp[maxn];
	auto check = [](int x)
	{
		try(i,1,n) temp[i] = a[i] + abs(i - x);
		std::nth_element(temp + 1,temp + mid,temp + n + 1);
		register int goal = std::max(temp[mid],std::max(x,n-x+1));
		int ret = 0;
		try(i,1,n) ret += abs(temp[i] - goal);
		return ret;
	};
	inline short main()
	{
		file(c);
		io >> n; mid = (1 + n) >> 1;
		try(i,1,n) io >> a[i];
		int curans = check(mid),cur = mid;
		double t = 100000;
	
		auto getrnd = []() -> double
		{return (double)(rand() - rand()) / (double)(RAND_MAX);};

		while(t >= 1e-7)
		{
			register int x = cur + t * getrnd();
			x = std::max(1ll,x); x = std::min(n,x);
			int temp = check(x);
			int delta = temp - curans;
			if(delta < 0 or exp(-delta/t) / (RAND_MAX) > rand())
				curans = temp,cur = x;
			ans = std::min(curans,ans);
			t *= 0.98;
		}
		cout<<ans<<endl;
		return 0;
	}
}
signed main(){return xin::main();}

擒敌拳

这个打的是一个组合拳

一个暴力的单调站就能有 \(70pts\),然后我们对于单调递增的那个进行斜率优化就好。。



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(a) FILE *FI = freopen(#a".in","r",stdin); FI = freopen(#a".out","w",stdout);
	#define debug cout<<"debug"<<endl
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
}
#define int long long
using namespace xin_io; static const int maxn = 1e7+10,inf = 1e9+10,llinf = 1e18+10;
namespace xin
{
	class xin_data
	{
		public:
			int pos,val;
			xin_data(){}
			xin_data(int pos,int val):pos(pos),val(val){}
	}st[maxn];
	int zhi = 0;
	int n,ms,a[maxn];
	int l[maxn],r[maxn];
	bool sp = 1;
	class xin_deque
	{
		public:
			int q[maxn],l,r;
			std::function<int()> front = [&]() -> int{return q[r];};
			std::function<int()> exfro = [&]() -> int{return q[r-1];};
			std::function<int()> back  = [&]() -> int{return q[l];};
			std::function<int()> exbac = [&]() -> int{return q[l+1];};
			std::function<void()> pop_back = [&]() -> void{l++;};
			std::function<void()> pop_front = [&]() -> void{r--;};
			std::function<void(int x)> push_front = [&](int x) -> void{q[++r] = x;};
			std::function<int()> size = [&]() -> int{return r - l + 1;};
	}q;
	auto special = []() -> void
	{
		n = ms;
		auto get_y = [=](int x) -> int{return a[x] * x - a[x];};
		auto slope = [=](int x,int y) -> double{return (double)(get_y(x) - get_y(y)) / (double)(a[x] - a[y]);};
		q.l = n + 1; q.r = n; int ans = -llinf;
		printf("%lld ",a[1]); q.push_front(1);
		try(i,2,n)
		{
			while(q.size() - 1 and slope(q.exbac(),q.back()) <= i) q.pop_back();
			ans = std::max(a[i],a[q.back()] * i - get_y(q.back()));
			while(q.size() - 1 and slope(i,q.front()) <= slope(q.front(),q.exfro())) q.pop_front();
			q.push_front(i); 
			printf("%lld ",ans);
		}
	};
	inline short main()
	{
		file(b)
		io >> ms;
		try(i,1,ms) 
		{
			io >> a[i];
			if(i-1 and a[i] < a[i-1]) sp = 0;
		}
//		sp = 0;
		if(sp) return special(),0;
		st[++zhi] = xin_data(0,-inf);
		int ans = 0;
		try(i,1,ms)
		{
			while(zhi and st[zhi].val >= a[i]) zhi --;
			st[++zhi] = xin_data(i,a[i]);
			try(j,1,zhi)
				ans = std::max(ans,(i - st[j].pos) * st[j+1].val);
			printf("%lld ",ans);
		}
		return 0;
	}
}
signed main() {return xin::main();}

边数

咕。。。

posted @ 2021-09-25 20:13  NP2Z  阅读(46)  评论(0编辑  收藏  举报