[考试总结]noip模拟59
这个新机房首模拟就做的很烂。。。
不过话说新机房真的强!!!!
这个东西是真的顶。
不废话了。。
柱状图
一个退火就能搞定。
只不过难度在如何对于一个最大高度然后进行 \(\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();}
边数
咕。。。