[Race] to improve the simulation test Jizhong Group A 19.8.17

Task.1 oblique line

Title effect: on a plane with a \ (n-\) points given \ (P, Q \) , the two points to find that they are located in the plane of the numerical slope of the line closest to \ (\ frac {P} { } Q \) . For the same line selection closeness smaller slope.

Data range: \ (2 \ Leq N \ Leq 2 \ ^ 10 5,1 Times \ Leq P, Q, X, Y \ ^. 9 Leq 10 \) , the slope of the straight line passing through the two points does not exist for the \ (0 \) or positive infinity.

In the examination room thought of a less naive idea, the rotating coordinate system to \ (Y \) axis is parallel to a slope of \ (\ frac {P} { Q} \) position of the straight line, this is probably:

Abscissa of each point calculated in the new coordinate system is \ (\ FRAC-Px Qy {} {\ sqrt {P ^ 2 + Q ^ 2}} \) , the following is very annoying, but and \ (X, y \) has nothing to do, so let it disappear into \ (Px-Qy \) .

Found that the slope of straight line passing through the abscissa point close to very close \ (\ FRAC {P} {Q} \) , we sorted according to the calculated slope abscissa point adjacent picture.

But this method hung up, I should have written, in fact, this approach has been very close to a positive solution, there is no problem on the idea.

We then become concrete practice one thing: put in a lot of new coordinate system \ (x = c \) parallel \ (y \) axis is a straight line, to explore the optimal solution would be somewhere.

Figure:

Obviously, according to the \ (X \) three points close to the sorted \ (A, B, C \) , the optimal solution must be \ (AB \) or \ (the BC \) fetch, rather than \ (AC \) ( \ (B \) points on the matter had \ (AC \) what position between the straight line \ (AC \) are not \ (AB, BC \) excellent).

And \ (STD \) approach gives the slope of each through its own points of \ (\ frac {P} { Q} \) intercept line ordering, and the adjacent point in the sorted from calculating the optimal solution, the correctness of the proof consistent with the above process. Complexity \ (O (N log N) \) .

Pit on the realization: \ (std \) suggested that we write the score class to avoid accuracy errors, but almost all are \ (long \ double \) past ...

Code:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

template<class T>void read(T &x){
    x=0; char c=getchar();
    while(c<'0'||'9'<c)c=getchar();
    while('0'<=c&&c<='9'){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
}
typedef long long ll;
typedef long double db;
const int N=200050;
const db e=1e-15;
int n;
ll P,Q,p,q;
struct point{ll x,y,c;}a[N];
ll gcd(ll _a,ll _b){return _b==0?_a:gcd(_b,_a%_b);}
ll absl(ll _a){return _a>0?_a:-_a;}
db absd(db _a){return _a>0?_a:-_a;}
bool cmp(point x,point y){return x.c<y.c;}

int main(){
    freopen("slope.in","r",stdin);
    freopen("slope.out","w",stdout);
    read(n); read(P); read(Q);
    ll d=gcd(P,Q); P/=d; Q/=d;
    for(int i=1,x,y;i<=n;i++){
        read(x); read(y);
        a[i]=(point){x,y,1ll*Q*y-1ll*P*x};
    }
    sort(a+1,a+n+1,cmp);
    ll tp,tq,p,q;
    db r=1e10,t,s=(db)P/(db)Q;
    for(int i=1;i<n;i++){
        tp=a[i].y-a[i+1].y;
        tq=a[i].x-a[i+1].x;
        if(tp*tq<0) continue;
        tp=absl(tp); tq=absl(tq);
        d=gcd(tp,tq); tp/=d; tq/=d;
        t=absd((db)tp/(db)tq-s);
        if(r-t>e) r=t, p=tp, q=tq;
    }
    printf("%lld/%lld\n",p,q);
    return 0;
}

Task.2 minimum

题目大意:有一个长度为 \(n\) 的序列 \(a\),定义一段区间 \([l,r]\) 的价值为 \(f(min^r_{i=l}a_i)=Ax^3+Bx^2+Cx+D\)。现在需要你把区间分成若干段,求分割后所有区间的价值的最大和。

数据范围:\(1\leq N\leq 2\times 10^5,\forall |f(x)|\leq 10^{13}\),输入的数据均在 \(int\) 范围内。

咋一看式子和求的东西以为是斜率优化?毕竟那个 \(O(N^2)\)\(dp\)还是很明显的:\(dp_i=max\{dp_j+f(min^r_{i=l}a_i)\}\)。接下来就是考虑优化它了,变成带 \(log\) 或者线性都会很好。

但是最小值有些棘手,我甚至不知道该怎么描述。但是在转移的过程中,随着 \(i\) 的增加, \(i\) 之前某些区间 \([l,r]\) 内的位置到 \(i\) 的最小值都是相同的,这个时候区间内的最优解一定是 \(dp\) 值最大的那一个。利用这个性质,如果我们能知道哪些区间里的位置到 \(i\) 的最小值相同,我们就能避免一些无用的转移。

这个问题就转化成了求 \(i\) 之前离 \(i\) 最近的位置 \(x\) ,使 \(x\) 之后的位置到 \(i\) 的最小值都是 \(a_x\),再求 \(x\) 之前离 \(x\) 最近的位置 \(y\),使 \(y\)\(x-1\) 的位置到 \(i\) 的最小值都为 \(a_y\) ...... 这个问题就一个经典的单调栈问题,维护一个栈顶到栈底递减的单调栈就可以了。

再利用单调栈来优化转移:当 \(a_i\) 入栈前退栈时,把退栈的位置的最值记录下来,利用退栈的最值更新 \(dp_i\),再把最值也存下来(可以存在栈里)。复杂度 \(O(N)\)

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

template<class T>void read(T &x){
    x=0; bool f=0; char c=getchar();
    while(c<'0'||'9'<c){f|=(c=='-'); c=getchar();}
    while('0'<=c&&c<='9'){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
    x=f?-x:x;
}
typedef long long ll;
const int N=200050;
int n,A,B,C,D;
int a[N],top;
struct node{int i; ll v;}st[N];
ll f[N];

ll F(int x){return 1ll*A*x*x*x+1ll*B*x*x+1ll*C*x+D;}

int main(){
    freopen("min.in","r",stdin);
    freopen("min.out","w",stdout);
    read(n); read(A); read(B); read(C); read(D);
    for(int i=1;i<=n;i++) read(a[i]);
    ll tmp=0;
    for(int i=1;i<=n;i++){
        tmp=f[i-1];
        while(top&&a[st[top].i]>a[i]) tmp=max(tmp,st[top--].v);
        f[i]=tmp+F(a[i]);
        if(top) f[i]=max(f[i],f[st[top].i]);
        st[++top]=(node){i,tmp};
    }
    printf("%lld\n",f[n]);
    return 0;
}

Task.3 安排

题目大意:给出长度为 \(n\) 的排列 \(A,B\),每次操作可以选择 \(A\) 中的一段区间 \([l,r]\),交换区间内最大值最小值的位置。求一种在 \(345678\) 次内把 \(A\) 变成 \(B\) 的方法。

数据范围:\(1\leq N\leq 4096\)

目前还不会做...

“您能再~讲一遍吗?”

Guess you like

Origin www.cnblogs.com/opethrax/p/11369880.html