AtCoder Grand Contest 007 solution to a problem

Portal

\(A\)

Gugu Gu

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=15;
char mp[N][N];int vis[N][N],n,m;
bool dfs(int x,int y){
    vis[x][y]=1;
    if(x==n&&y==m)return true;
    R int c=0;
    if(x<n&&mp[x+1][y]=='#')++c;
    if(y<m&&mp[x][y+1]=='#')++c;
    if(c!=1)return false;
    if(x<n&&mp[x+1][y]=='#')return dfs(x+1,y);
    if(y<m&&mp[x][y+1]=='#')return dfs(x,y+1);
}
int main(){
    scanf("%d%d",&n,&m);
    fp(i,1,n)scanf("%s",mp[i]+1);
    if(mp[1][1]!='#'||mp[n][m]!='#')return puts("Impossible"),0;
    if(!dfs(1,1))return puts("Impossible"),0;
    fp(i,1,n)fp(j,1,m)if((mp[i][j]=='#')!=vis[i][j])return puts("Impossible"),0;
    return puts("Possible"),0;
}

\(B\)

First \ (A \) and \ (B \) are set to \ (1 \) to the \ (n-\) to satisfy the first condition the second

We found that if \ (a_i \) to \ (a_n \) all add \ (the X-\) , and \ (b_1 \) to \ (b_i \) all add \ (the X-\) , can \ ( a_i + b_i \) relative increase \ (X \) and still satisfy the first condition the second

So we let \ (p_i \) relative increase \ (i \) The third condition can be met, the maximum number is \ (O (n ^ 2) \) level, no more than \ (10 ^ 9 \)

const int N=1e5+5;
int a[N],b[N],p[N],n;
int main(){
    scanf("%d",&n);
    fp(i,1,n)scanf("%d",&p[i]),a[p[i]]+=i,b[p[i]]+=i;
    fp(i,1,n)a[i]+=a[i-1];fd(i,n,1)b[i]+=b[i+1];
    fp(i,1,n)printf("%d%c",a[i]+i," \n"[i==n]);
    fp(i,1,n)printf("%d%c",b[i]+n-i+1," \n"[i==n]);
    return 0;
}

\(C\)

Totally unexpected ah ......

First, we have converted to \ (2n + 1 \) th items, each adjacent two randomly deleting, and find a desired distance

We found that from the outset is a arithmetic sequence, and if desired to maintain the distance between every two points, then after one operation is still arithmetic sequence

Specific proof then, if after deleting apparently two points on the boundary or arithmetic operation, or if for a length \ (d + kx \) that a length of, by deleting two vertices after this becomes \ (3D 3kx + \) , was why \ (D_i \) represents the \ (I \) points and \ (i + 1 \) a desired distance from points, \ (D_i '\) is the operation after the desired distance, then a total of \ (2N \) species puncturing method, the \ (d_i '= {i \ over 2n} (d_i + 2x) + {1 \ over 2n} (3d_i + 3x) + {2n-i -1 \ = {D_i} over 2N 2N + 2 \ + {D_i} over 2N + 2i. 3 \ over 2N} X \) , so \ (x '= d_i'-d_ {i-1}' = {2n + 4 \ over 2x} = {X n-2 + \} n-X over \) , is a fixed value

Then again consider new arithmetic sequence of first entry, if the delete \ (2 \) , the first term becomes \ (D + 2x \) , if the delete \ (3 \) , the first term becomes \ (3x + 3D \) , otherwise unchanged, so the new first item \ (d_1 ^ { '} = \ frac {1} {2n} * (d_1 + 2x) + \ frac {1} {2n} * ( 3d_1 + 3x) + \ frac { 2n-2} {2n} * d_1 = \ frac {(2n + 2) d_1 + 5x} {2n} \)

Then each calculation can be

int n;double d,x,res;
int main(){
    scanf("%d%lf%lf",&n,&d,&x);
    for(;n;--n){
        res+=(d+((n<<1)-1)*x*0.5),
        d=(((n<<1)+2)*d+5*x)/(n<<1),
        x=(n+2)*x/n;
    }
    printf("%.12lf\n",res);
    return 0;
}

\(D\)

First, we write a violent easy, provided \ (F_i \) represents the front \ (I \) the minimum number of all processed in time, the \ (f_i = \ min_ {j <i} (f_j + \ max (t, (a_i-a_ {j + 1 }))) \)

Since \ (\ max (t, ( a_i-a_ {j + 1}) \) cut-off point is with \ (I \) increments not drop, so we can directly demarcation points respectively on both sides of the answer \ ( set \) recorded and then directly query like

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef long long ll;
const int N=5e5+5;const ll inf=1e18;
int n,t,e,a[N];ll f[N];
inline ll min(R ll x,R ll y){return x<y?x:y;}
inline ll max(R ll x,R ll y){return x>y?x:y;}
struct Queue{
    priority_queue<ll,vector<ll>,greater<ll> >A,B;
    inline void push(R ll x){A.push(x);}
    inline void pop(R ll x){B.push(x);}
    inline ll top(){
        while(!B.empty()&&A.top()==B.top())A.pop(),B.pop();
        return A.empty()?inf:A.top();
    } 
}s1,s2;
int main(){
    scanf("%d%d%d",&n,&e,&t);
    fp(i,1,n)scanf("%d",&a[i]);
    s2.push(0);
    for(R int i=1,j=0;i<=n;++i){
        while(j<i&&((a[i]-a[j+1])<<1)>=t)s1.push(f[j]-(a[j+1]<<1)),s2.pop(f[j]),++j;
        f[i]=inf,cmin(f[i],s1.top()+(a[i]<<1)),cmin(f[i],s2.top()+t);
        s2.push(f[i]);
    }
    printf("%lld\n",f[n]+e);
    return 0;
}

\(E\)

First-half will certainly be the answer, and because each side can only go through twice, after entering a sub tree in which all nodes have been traversed in order to come out

For each point, a record state \ ((a, b) \ ) represent a legal path is spent \ (a \) the price went to a leaf from the current node, spend \ (b \) price from a one leaves to go back to the current node, then for the left subtree \ ((a, b) \ ) and right subtree \ ((c, d) \) , only when \ (b + w_i + c + w_j \ leq mid \) when they can be combined into \ ((a + w_i, w_j d +) \) , empathy also determine what can in turn be combined into \ ((c + w_j, b + w_i) \)

Each time the son of state about the merger, as long as the final \ (1 \) status dot on the existence of a legitimate explanation \ (mid \) feasible

There is an optimization is for a legitimate \ (a \) , its corresponding \ (b \) must be as small as possible, then we can for the left subtree sorted by the first dimension, according to the first right sub-tree two sorting, such complexity can be combined to optimize \ (O (n) \) of

However, the number of states may be more, so every time we use a small number of states to merge state large number, so the number of states \ (S_u \ Leq 2 \ min (S_i, S_j) \) , the total number of states is \ ( O (n \ log n) \ ) , then the total complexity is \ (O (n \ log ^ 2 n) \)

However, more strange is that if I use a small number of large state not to merge \ (T \) instead \ (WA \) ...... ah ...... good fans

//quming
#include<bits/stdc++.h>
#define R register
#define pb push_back
#define fi first
#define se second
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef pair<int,int> pi;
typedef vector<pi> vc; 
const int N=5e5+5;
int ls[N],rs[N],w[N],mn[N],n,l,r,mid,ans;vc f[N];
inline int min(R int x,R int y){return x<y?x:y;}
inline void swap(R int &x,R int &y){R int t=x;x=y,y=t;}
inline bool cmpx(const pi &x,const pi &y){return x.fi<y.fi;}
inline bool cmpy(const pi &x,const pi &y){return x.se<y.se;}
void merge(vc &a,vc &ls,vc &rs){
    R int n=ls.size(),m=rs.size();
    if(!n||!m)return;
    if(n>m)ls.swap(rs),swap(n,m);
    sort(ls.begin(),ls.end(),cmpy);
    sort(rs.begin(),rs.end(),cmpx);
    mn[0]=rs[0].se;fp(i,1,m-1)mn[i]=min(mn[i-1],rs[i].se);
    for(R int i=0,j=m-1;i<n;++i){
        while(j>=0&&ls[i].se+rs[j].fi>mid)--j;
        if(j<0)break;a.pb(pi(ls[i].fi,mn[j]));
    }
    sort(ls.begin(),ls.end(),cmpx);
    sort(rs.begin(),rs.end(),cmpy);
    mn[0]=rs[0].fi;fp(i,1,m-1)mn[i]=min(mn[i-1],rs[i].fi);
    for(R int i=0,j=m-1;i<n;++i){
        while(j>=0&&ls[i].fi+rs[j].se>mid)--j;
        if(j<0)break;a.pb(pi(mn[j],ls[i].se));
    }
}
void dfs(int u){
    f[u].clear();if(!ls[u])return f[u].pb(pi(w[u],w[u])),void();
    dfs(ls[u]),dfs(rs[u]);
    merge(f[u],f[ls[u]],f[rs[u]]);
    for(auto &v:f[u])v.fi+=w[u],v.se+=w[u];
}
int main(){
    scanf("%d",&n);
    for(R int i=2,fa,x;i<=n;++i){
        scanf("%d%d",&fa,&x);
        (ls[fa]?rs[fa]:ls[fa])=i,w[i]=x;
    }
    l=0,r=1e9,ans=1e9;
    while(l<=r){
        mid=(l+r)>>1,dfs(1);
        f[1].empty()?l=mid+1:(ans=mid,r=mid-1);
    }
    printf("%d\n",ans);
    return 0;
}

\(F\)

Good fans ......

First, we found a letter down the track regarded as one path, then this path will be a polyline, polyline and the sooner the better turning

So we have to \ (t \) from the back of greedy match, found \ (s \) position in the rearmost able to match, and then determine whether there are previous polyline intersection

I still say the feeling is not very clear ...... I recommend a look at Figure solution to a problem of official

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=1e6+5;
char a[N],b[N];int q[N],h,t,n,res;
int main(){
    scanf("%d%s%s",&n,a+1,b+1);
    if(!strcmp(a+1,b+1))return puts("0"),0;
    h=1,t=0;
    for(R int i=n,p=n;i;--i)if(b[i]!=b[i-1]){
        cmin(p,i);while(p&&a[p]!=b[i])--p;
        if(!p)return puts("-1"),0;
        while(h<=t&&q[h]-(t-h+1)>=i)++h;
        q[++t]=p;
        if(i!=p)cmax(res,t-h+1);
    }
    printf("%d\n",res+1);
    return 0;
}

Guess you like

Origin www.cnblogs.com/yuanquming/p/11438531.html