8月9日数据结构考试 解析

A. 黑桃城

得分:100

解析:

这题挺水的吧,直接把dfs之后的序列映射到线段树的一段区间维护即可

反正我40分钟就A了,自认为还是挺简单的。

这题好像也是比赛中AC人数最多的,。。。

还有就是注意不要用不同步的cin,小心TLE

然后 我好像找到了原题 CF077E Danil and a Part-time Job

除输入外一模一样。。。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<cstring>
#define For(i,j,k)  for(ll i=j;i<=k;++i)
#define Dow(i,j,k)  for(ll i=k;i>=j;--i)
#define M 100010
#define pb push_back
#define ll  long long
using namespace std;
inline ll read()
{
    ll t=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {c=getchar();}
    while(c<='9'&&c>='0')   t=t*10+c-48,c=getchar();
    return t*f;
}
int poi[M<<2],nxt[M<<2],f[M<<2],cnt,n,m;
char opt[10],s[M<<2];
struct tree{int v,sz;}  tr[M<<2];
int tag[M<<2];
int in[M<<2],out[M<<2],tim,on[M<<2],to[M<<2];
inline void add(int x,int y){
    poi[++cnt]=y;
    nxt[cnt]=f[x];
    f[x]=cnt;
}
inline void dfs(int x,int fa){
    in[x]=++tim;to[tim]=x;
    for(int i=f[x];i;i=nxt[i]){
        if(poi[i]==fa)  continue;
        dfs(poi[i],x);
    }
    out[x]=tim;
}
inline void up(int x){
    tr[x].v=tr[x<<1|1].v+tr[x<<1].v;
    tr[x].sz=tr[x<<1|1].sz+tr[x<<1].sz;
}
inline void build(int x,int l,int r){
    if(l==r){
        tr[x].v=on[to[l]];
        tr[x].sz=1;
        return;
    }
    int mid=l+r>>1;
    build(x<<1,l,mid);build(x<<1|1,mid+1,r);
    up(x);
}
inline void push(int x){
    if(tag[x]){
        tag[x<<1]^=1;tag[x<<1|1]^=1;
        tr[x<<1].v=tr[x<<1].sz-tr[x<<1].v;tr[x<<1|1].v=tr[x<<1|1].sz-tr[x<<1|1].v;
        tag[x]=0;
    }
}
inline int ask(int x,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr) return tr[x].v;
    int mid=l+r>>1;
    push(x);
    int sum=0;
    if(ql<=mid) sum+=ask(x<<1,l,mid,ql,qr);
    if(qr >mid) sum+=ask(x<<1|1,mid+1,r,ql,qr);
    up(x);
    return sum; 
}
inline void change(int x,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr){
        tr[x].v=tr[x].sz-tr[x].v;
        tag[x]^=1;
        return;
    }
    int mid=l+r>>1;
    push(x);
    if(ql<=mid) change(x<<1,l,mid,ql,qr);
    if(qr >mid) change(x<<1|1,mid+1,r,ql,qr);
    up(x);
}
int main(){
    n=read(),m=read();
    scanf("%s",&s) ;
    For (i,1,n) on[i]=s[i-1]-'0' ;
    For (i,1,n-1){
        int a=read(),b=read() ;
        add(a,b) ;
    }
    dfs(1,1);
    build(1,1,n);
    For(i,1,m){
        scanf("%s",opt+1);
        if(opt[1]=='Q') {   
            int x=read();
            printf("%d\n",ask(1,1,n,in[x],out[x]));
        }
        else{
            int x=read();
            change(1,1,n,in[x],out[x]);
        }
    }
}

B. 红五月

得分:42

预期:42 ~ 67

这题其实是我花费时间最长是哪个的一道题目,几乎占用了我一半的时间,以至于我没有拿到C题的49分,没有上两百(第一

我先打了暴力,前42分其实很好拿,直接暴力修改判断即可,但这么简单我却打了1个多快2个小时,这得要加强一下码力啊。

e

这题其实就是一个动态查询,修改的树上问题,其实一个树剖就能搞定。

关键思考修改操作

考虑跨区间的情况,细心讨论一下。

巨佬现场67代码(%%%PQF):

#include<bits/stdc++.h>
using namespace std;
int fa[100001],d[100001];
vector <int> E[100001];
int c[200001];
int n,m,a[100001],u,v,s0,s1,num;
int dfn[100001],seq[100001];
int lca (int u,int v)
{
    if (d[u]!=d[v])
    {
        if (d[u]<d[v]) swap(u,v);
        while (d[u]>d[v])
        u=fa[u];
    }
    while (u!=v)
    u=fa[u],v=fa[v];
    return u;
}
string str;
void dfs (int x)
{
    for (auto i:E[x])
    {
        if (i==fa[x]) continue;
        fa[i]=x;
        d[i]=d[x]+1;
        dfs(i);
    }
    return;
}
void dfs1 (int x)
{
    dfn[++num]=x;
    seq[x]=num;
    for (auto i:E[x])
    {
        if (i==fa[x]) continue;
        fa[i]=x;
        d[i]=d[x]+1;
        dfs1(i);
    }
    return;
}
struct data
{
    int l,r,len,lazy,s;
}tr[400001];
void build (int x,int l,int r)
{
    tr[x].l=l;
    tr[x].r=r;
    tr[x].len=r-l+1;
    tr[x].lazy=-1;
    if (l==r)
    {
        tr[x].s=a[seq[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
    tr[x].s=tr[x<<1].s+tr[x<<1|1].s;
    return;
}
void pushdown (int x)
{
    int p=tr[x].lazy;
    tr[x<<1].lazy=p;
    tr[x<<1|1].lazy=p;
    tr[x<<1].s=tr[x<<1].len*p;
    tr[x<<1|1].s=tr[x<<1|1].len*p;
    tr[x].lazy=-1;
}
int sum (int x,int l,int r)
{
    int ll=tr[x].l,rr=tr[x].r;
    if (l<=ll && r>=rr) return tr[x].s;
    if (ll>r) return 0;
    if (rr<l) return 0;
    if (tr[x].lazy!=-1) pushdown(x);
    int mid=(ll+rr)>>1;
    if (l>mid) return sum(x<<1|1,l,r);
        else if (r<=mid) return sum(x<<1,l,r);
            else return sum(x<<1,l,mid)+sum(x<<1|1,mid+1,r);
}
void change (int x,int l,int r,int s)
{
    if (l>r) return;
    //printf("%d %d %d %d\n",x,l,r,s);
    int ll=tr[x].l,rr=tr[x].r;
    if (l<=ll && r>=rr)
    {
        tr[x].lazy=s;
        tr[x].s=tr[x].len*s;
        return;
    }
    if (ll>r) return;
    if (rr<l) return;
    if (tr[x].lazy!=-1) pushdown(x);
    int mid=(ll+rr)>>1;
    if (l>mid) change(x<<1|1,l,r,s);
        else if (r<=mid) change(x<<1,l,r,s);
            else { change(x<<1,l,mid,s); change(x<<1|1,mid+1,r,s); }
    tr[x].s=tr[x<<1].s+tr[x<<1|1].s;
    return;
}
bool doit (int u,int v)
{
    int fu=dfn[u],fv=dfn[v];
    if (fu>fv)
    {
        swap(fu,fv);
        swap(u,v);
    }
    int z1=sum(1,fu,fv);
    int z0=fv-fu+1-z1;
    //printf("%d %d\n",z0,z1);
    if ((z0&1) && (z1&1)) return false;
    if (z0&1)
    {
        change(1,fu,fu+z0/2-1,0);
        change(1,fu+z0/2,fu+z0/2+z1/2-1,1);
        change(1,fu+z0/2+z1/2,fu+z0/2+z1/2,0);
        change(1,fu+z0/2+z1/2+1,fu+z0/2+z1,1);
        change(1,fu+z0/2+z1+1,fv,0);
        return true;
    }
    change(1,fu,fu+z0/2-1,0);
    change(1,fu+z0/2,fu+z0/2+z1-1,1);
    change(1,fu+z0/2+z1,fv,0);
    return true;
}
int main()
{
    scanf("%d%d",&n,&m);
    cin>>str;
    for (int i=1;i<=n;i++)
    a[i]=str[i-1]-48;
    for (int i=1;i<=n-1;i++)
    {
        scanf("%d%d",&u,&v);
        E[u].push_back(v);
        E[v].push_back(u);
    }
    if (n<=1000)
    {
        dfs(1);
        /*
        for (int i=1;i<=n;i++)
        printf("%d %d\n",fa[i],d[i]);
        */
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            int w=lca(u,v);
            s0=s1=0;
            for (int x=u;x!=w;x=fa[x])
            {
                if (a[x]) s1++;
                    else s0++;
            }
            for (int x=v;x!=w;x=fa[x])
            {
                if (a[x]) s1++;
                    else s0++;
            }
            if (a[w]) s1++;
                else s0++;
            //printf("%d\n%d %d\n",w,s0,s1);
            if ((s1&1) && (s0&1))
            {
                printf("No\n");
                continue;
            }
            printf("Yes\n");
            if (s1&1)
            {
                num=0;
                for (int x=u;x!=w;x=fa[x])
                c[++num]=x;
                c[++num]=w;
                num=d[u]+d[v]-2*d[w]+1;
                for (int x=v;x!=w;x=fa[x])
                c[num--]=x;
                for (int i=1;i<=s0/2;i++)
                a[c[i]]=0;
                for (int i=s0/2+1;i<=s0/2+s1;i++)
                a[c[i]]=1;
                for (int i=s0/2+s1+1;i<=s0+s1;i++)
                a[c[i]]=0;
            }
                else if (s0&1)
            {
                num=0;
                for (int x=u;x!=w;x=fa[x])
                c[++num]=x;
                c[++num]=w;
                num=d[u]+d[v]-2*d[w]+1;
                for (int x=v;x!=w;x=fa[x])
                c[num--]=x;
                for (int i=1;i<=s0/2;i++)
                a[c[i]]=0;
                for (int i=s0/2+1;i<=s0/2+s1/2;i++)
                a[c[i]]=1;
                a[c[s0/2+s1/2+1]]=0;
                for (int i=s0/2+s1/2+2;i<=s0/2+s1+1;i++)
                a[c[i]]=1;
                for (int i=s0/2+s1+2;i<=s0+s1;i++)
                a[c[i]]=0;
            }
                else 
            {
                num=0;
                for (int x=u;x!=w;x=fa[x])
                c[++num]=x;
                c[++num]=w;
                num=d[u]+d[v]-2*d[w]+1;
                for (int x=v;x!=w;x=fa[x])
                c[num--]=x;
                for (int i=1;i<=s0/2;i++)
                a[c[i]]=0;
                for (int i=s0/2+1;i<=s0/2+s1;i++)
                a[c[i]]=1;
                for (int i=s0/2+s1+1;i<=s0+s1;i++)
                a[c[i]]=0;
            }
            /*
            for (int i=1;i<=n;i++)
            printf("%d ",a[i]);
            printf("\n");
            num=d[u]+d[v]-2*d[w]+1;
            for (int i=1;i<=num;i++)
            printf("%d ",c[i]);
            printf("\n");
            printf("\n");
            */
        }
        return 0;
    }
    int k;
    for (k=1;k<=n;k++)
    if (E[k].size()==1) break;
    //printf("%d\n",k);
    dfs1(k);
    build(1,1,n);
    /*
    for (int i=1;i<=n;i++)
    printf("%d ",dfn[i]);
    printf("\n");
    for (int i=1;i<=9;i++)
    printf("%d %d  %d %d\n",tr[i].l,tr[i].r,tr[i].lazy,tr[i].s);
    printf("\n");
    */
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&u,&v);
        if (doit(u,v)) printf("Yes\n");
            else printf("No\n");
        /*
        for (int i=1;i<=9;i++)
        printf("%d %d  %d %d\n",tr[i].l,tr[i].r,tr[i].lazy,tr[i].s);
        printf("\n");
        */
    }
    return 0;
}
/*
5 10
01011
1 5
2 4
1 3
3 2
*/

标算(%%% mjy0724 (RP- -))(太懒不想写,反正考试也写不出来):

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long ll ;
#define rep(i, a, b) for (int i = a; i <= b; ++ i) 
const int N = 2e5 + 5 ;
using namespace std ;

char s[N] ;
int n, m, e, ter[N << 1], nxt[N << 1], lnk[N], dep[N], cnt ;
int L[N], R[N], bel[N], sz[N], pos[N], fa[N] ;
struct node {
    int cov[2], len, tag ;
    node() {}
    node(int _x, int _y) {
        cov[0] = _x ;
        cov[1] = _y ;
    }
    node friend operator + (node a, node b) {
        return node(a.cov[0] + b.cov[0], a.cov[1] + b.cov[1]) ;
    }
} tr[N << 2] ;
struct intv {
    int l, r ;
    intv() {}
    intv(int _l, int _r) {
        l = _l ;
        r = _r ;
    }
} d[N] ;

void add(int x, int y) {
    ter[++ e] = y ;
    nxt[e] = lnk[x] ;
    lnk[x] = e ;
}

void dfs(int p, int las) {
    sz[p] = 1 ;
    for (int i = lnk[p] ; i; i = nxt[i]) if (ter[i] != las) {
        fa[ter[i]] = p ;
        dep[ter[i]] = dep[p] + 1 ;
        dfs(ter[i], p) ;
        sz[p] += sz[ter[i]] ;
    }
}

void Dfs(int p, int chain) {
    bel[p] = chain ;
    L[p] = ++ cnt ;
    pos[cnt] = p ;
    int k = 0 ;
    for (int i = lnk[p] ; i; i = nxt[i]) {
        int v = ter[i] ;
        if (dep[v] > dep[p] && sz[v] > sz[k]) {
            k = v ;
        }
    }
    if (k) Dfs(k, chain) ;
    for (int i = lnk[p] ; i; i = nxt[i]) {
        int v = ter[i] ;
        if (dep[v] > dep[p] && v != k) Dfs(v, v) ;
    } 
    R[p] = cnt ;
}

int lca(int x, int y) {
    for ( ; bel[x] != bel[y] ; ) {
        if (dep[bel[x]] >= dep[bel[y]]) {
            x = fa[bel[x]] ;
        } else {
            y = fa[bel[y]] ;
        }
    }
    return dep[x] < dep[y] ? x : y ;
}

void psd(int p) {
    int l = p << 1, r = l | 1 ;
    if (tr[p].tag != - 1) {
        rep(i, 0, 1) {
            tr[l].cov[i] = 0 ;
            tr[r].cov[i] = 0 ;
        }
        tr[l].tag = tr[r].tag = tr[p].tag ;
        tr[l].cov[tr[p].tag] = tr[l].len ;
        tr[r].cov[tr[p].tag] = tr[r].len ;
        tr[p].tag = - 1 ;
    }
}

void upd(int p) {
    int l = p << 1, r = l | 1 ;
    rep(i, 0, 1) {
        tr[p].cov[i] = tr[l].cov[i] + tr[r].cov[i] ;
    }
}

void build(int p, int l, int r) {
    tr[p].tag = - 1 ;
    tr[p].len = r - l + 1 ;
    if (l == r) {
        rep(i, 0, 1) {
            tr[p].cov[i] = 0 ;
        }
        tr[p].cov[s[pos[l]] - '0'] ++ ;
        return ;
    }
    int mid = (l + r) / 2 ;
    build(p << 1, l, mid) ;
    build(p << 1 | 1, mid + 1, r) ;
    upd(p) ;
}

void modify(int p, int l, int r, int lx, int rx, int ave) {
    if (l == lx && r == rx) {
        tr[p].tag = ave ;
        rep(i, 0, 1) {
            tr[p].cov[i] = 0 ;
        }
        tr[p].cov[ave] = tr[p].len ;
        return ;
    }
    int mid = (l + r) / 2 ;
    psd(p) ;
    if (rx <= mid) modify(p << 1, l, mid, lx, rx, ave) ; else
    if (lx > mid) modify(p << 1 | 1, mid + 1, r, lx, rx, ave) ; else {
        modify(p << 1, l, mid, lx, mid, ave) ;
        modify(p << 1 | 1, mid + 1, r, mid + 1, rx, ave) ;
    }
    upd(p) ;
}

node query(int p, int l, int r, int lx, int rx) {
    if (l == lx && r == rx) {
        return tr[p] ;
    }
    int mid = (l + r) / 2 ;
    psd(p) ;
    if (rx <= mid) return query(p << 1, l, mid, lx, rx) ;
    if (lx > mid) return query(p << 1 | 1, mid + 1, r, lx, rx) ;
    return query(p << 1, l, mid, lx, mid) + query(p << 1 | 1, mid + 1, r, mid + 1, rx) ;
}

inline void Modi(int x, int l, int r, int c) {
    if (d[x].l <= d[x].r) {
        modify(1, 1, n, d[x].l + l - 1, d[x].l + r - 1, c) ;
    } else {
        modify(1, 1, n, d[x].l - r + 1, d[x].l - l + 1, c) ;
    }
}

inline intv Solve(intv cur, int sum, int c) {
    for ( ; sum > 0 ; ) {
        int len = abs(d[cur.l].r - d[cur.l].l) + 1 ;
        if (len - cur.r + 1 >= sum) {
            Modi(cur.l, cur.r, cur.r + sum - 1, c) ;
            cur.r += sum ;
            if (cur.r > len) {
                ++ cur.l ;
                cur.r = 1 ;
            }
            return cur ;
        } else {
            Modi(cur.l, cur.r, len, c) ;
            sum -= len - cur.r + 1 ;
            ++ cur.l ;
            cur.r = 1 ;
        }
    }
    return cur ;
}

int main() {
    scanf("%d%d", &n, &m) ;
    scanf("%s", s + 1) ;
    int x, y ;
    rep(i, 1, n - 1) {
        scanf("%d%d", &x, &y) ;
        add(x, y) ;
        add(y, x) ;
    }
    dfs(1, 0) ;
    Dfs(1, 1) ;
    build(1, 1, n) ;
    for ( ; m -- ; ) {
        scanf("%d%d", &x, &y) ;
        int t = lca(x, y), tot = 0 ;
        node res = node(0, 0) ;
        for ( ; bel[x] != bel[t] ; x = fa[bel[x]]) {
            res = res + query(1, 1, n, L[bel[x]], L[x]) ;
            d[++ tot] = intv(L[x], L[bel[x]]) ;
        }
        res = res + query(1, 1, n, L[t], L[x]) ;
        d[++ tot] = intv(L[x], L[t]) ;
        int mid = tot + 1 ;
        for ( ; bel[y] != bel[t] ; y = fa[bel[y]]) {
            res = res + query(1, 1, n, L[bel[y]], L[y]) ;
            d[++ tot] = intv(L[bel[y]], L[y]) ;
        }
        if (y != t) {
            res = res + query(1, 1, n, L[t] + 1, L[y]) ;
            d[++ tot] = intv(L[t] + 1, L[y]) ;
        }
        if (mid < tot) {
            reverse(d + mid, d + tot + 1) ;
        }
        if ((res.cov[0] & 1) && (res.cov[1] & 1)) {
            puts("No") ;
            continue ;
        }
        puts("Yes") ;
        intv inp = intv(1, 1) ;
        inp = Solve(inp, res.cov[0] / 2, 0) ;
        inp = Solve(inp, res.cov[1] / 2, 1) ;
        if (res.cov[0] & 1) {
            inp = Solve(inp, 1, 0) ; 
        }
        if (res.cov[1] & 1) {
            inp = Solve(inp, 1, 1) ;
        }
        inp = Solve(inp, res.cov[1] / 2, 1) ;
        inp = Solve(inp, res.cov[0] / 2, 0) ;
    }
    return 0 ; 
}

C.海棠溪

得分:17
预期:61

其实是个dp题,至于为什么出在数据结构考试中,你一会儿就知道了。(ヾ(>Д<;))))….. 逃

深搜17分

#include <bits/stdc++.h>
using namespace std ;
const int inf = INT_MAX/2 ;
int n,T,A,B,ans ;
int a[100010] ;
void dfs(int k,int A,int B,int sum){
    if (sum>ans) return ;
    if (k==T+1){
        if (ans>sum) ans=sum ;
        return ;
    }
    dfs(k+1,a[k],B,sum+(abs(a[k]-A))) ;
    dfs(k+1,A,a[k],sum+(abs(a[k]-B))) ;
}
int main(){
    scanf("%d%d%d%d",&n,&T,&A,&B);
    for (int i=1;i<=T;i++) scanf("%d",&a[i]) ;
    ans=inf ;
    dfs(1,A,B,0);
    cout<<ans<<endl ;
}

考虑dp

d p [ i ] [ j ] 表示现在处理到第i 个人,另一朵花在第j 个人手上的答
案。

d p [ i ] [ j ] + a b s ( x j x i + 1 ) 更新 d p [ i + 1 ] [ i ]
d p [ i ] [ j ] + a b s ( x i x i + 1 ) 更新 d p [ i + 1 ] [ j ]

这样要过 S u b t a s k 3 ,会 M L E ,滚动就61分

感谢XRY大佬

#include <bits/stdc++.h>
using namespace std ;
const int inf = 0x3f3f3f3f ;
const int N = 200000 ;
int n,T,A,B,ans ;
int DP[N],dp[N],a[N],b[N] ;
int main(){
    scanf("%d%d%d%d",&n,&T,&A,&B) ;
    for (int i=1;i<=T;i++) scanf("%d",&a[i]) ;
    memset(dp,0x3f,sizeof(dp)) ;
    memset(DP,0x3f,sizeof(DP)) ;
    DP[A]=abs(a[1]-B) ;
    DP[B]=abs(a[1]-A) ;
    for (int i=2;i<=T;i++){
        for (int j=1;j<=n;j++){
            dp[j]=min(dp[j],DP[j]+abs(a[i-1]-a[i])) ;
            dp[a[i-1]]=min(dp[a[i-1]],DP[j]+abs(j-a[i])) ;
        }
        memcpy(DP,dp,sizeof(DP)) ;
        memset(dp,0x3f,sizeof(dp)) ;
    }
    ans=inf;
    for (int i=1;i<=n;i++) ans=min(ans,DP[i]) ;
    printf("%d\n",ans) ;
}

Subtask 4:39 分
1 考虑用一个数据结构维护一下 f i
2 对于大部分的位置相当于是区间加了一个 | x i x i + 1 | 。对于 i 1 的位置要通过上一行整行来计算。
3 把绝对值拆掉处理方法:将第二维的含义修改成位置,这样加和减所对应的就是连续的区间了。
4 对于 f ? , i x i f ? , i + x i 分别维护。查询两次即可得到关于
f i , i 1 的答案。单点修改一下即可。
5 时间复杂度 O ( T l o g n )

此为mjy0724 的 标算

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long ll ; 
#define rep(i, a, b) for (int i = a; i <= b; ++ i) 
const int N = 2e5 + 5 ; 
const ll inf = 1e17 + 7 ;
using namespace std ;

int n, m, A, B, x[N] ;
ll bit[2][2][N], dist[N], f[2][N] ;

void put(int cx, int cy, int x, ll y) {
    for ( ; x <= n ; x += x & (- x)) bit[cx][cy][x] = min(bit[cx][cy][x], y) ;
}

ll get(int cx, int cy, int x) {
    ll res = inf ;
    for ( ; x ; x -= x & (- x)) res = min(res, bit[cx][cy][x]) ;
    return res ;
}

int main() {
    scanf("%d%d%d%d", &n, &m, &A, &B) ;
    rep(i, 1, m) scanf("%d", &x[i]) ;
    rep(i, 0, 1) rep(j, 0, 1) rep(k, 1, n) bit[i][j][k] = inf ;
    rep(i, 2, m) dist[i] = dist[i - 1] + abs(x[i] - x[i - 1]) ;
    f[0][0] = abs(B - x[1]), f[1][0] = abs(A - x[1]) ;
    put(0, 0, A, f[0][0] - dist[1] - A), put(0, 1, n - A + 1, f[0][0] - dist[1] + A) ;
    put(1, 0, B, f[1][0] - dist[1] - B), put(1, 1, n - B + 1, f[1][0] - dist[1] + B) ;
    rep(i, 1, m - 1) {
        f[0][i] = min(get(1, 0, x[i + 1]) + dist[i] + x[i + 1], get(1, 1, n - x[i + 1] + 1) + dist[i] - x[i + 1]) ;
        f[1][i] = min(get(0, 0, x[i + 1]) + dist[i] + x[i + 1], get(0, 1, n - x[i + 1] + 1) + dist[i] - x[i + 1]) ;
        put(0, 0, x[i], f[0][i] - dist[i + 1] - x[i]), put(0, 1, n - x[i] + 1, f[0][i] - dist[i + 1] + x[i]) ;
        put(1, 0, x[i], f[1][i] - dist[i + 1] - x[i]), put(1, 1, n - x[i] + 1, f[1][i] - dist[i + 1] + x[i]) ;
    }
    ll ans = inf ;
    rep(i, 0, m - 1) ans = min(ans, min(f[0][i], f[1][i]) + dist[m] - dist[i + 1]) ;
    printf("%lld\n", ans) ;
    return 0 ;
}

还有Smy 巨佬%%%orzorz 的 f h q t r e a p %%%%代码(太巨了)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define int long long
using namespace std;
int f[2000005],sum[2000005],g[2000005];
int a[2000005],n,T,A,B,minl,Root,tot;
struct node{
    int rch,lch,big,sma,val,key,bh; 
}t[2000005];
int seed=233;
int Rand(){
    return seed=seed*49271ll%2147483647;
}
void update(int now){
    int bh=t[now].bh;
    t[now].big=g[bh]-sum[bh+1]+a[bh];
    t[now].sma=g[bh]-sum[bh+1]-a[bh];
    if(t[now].lch){
        t[now].big=min(t[now].big,t[t[now].lch].big);
        t[now].sma=min(t[now].sma,t[t[now].lch].sma);               
    }
    if(t[now].rch){
        t[now].big=min(t[now].big,t[t[now].rch].big);
        t[now].sma=min(t[now].sma,t[t[now].rch].sma);               
    }
}
void split(int now,int &a,int &b,int k){
    if(now==0){
        a=b=0;
        return;
    }
    if(t[now].val<=k)
        a=now,split(t[now].rch,t[a].rch,b,k);
    else
        b=now,split(t[now].lch,a,t[b].lch,k);
    update(now);        
}
void merge(int &now,int a,int b){
    if(a==0||b==0){
        now=a+b;
        return;
    }
    if(t[a].key<t[b].key)
        now=a,merge(t[now].rch,t[a].rch,b);
    else
        now=b,merge(t[now].lch,a,t[b].lch);  
    update(now);
}
signed main(){
    scanf("%d%d%d%d",&n,&T,&A,&B);
    for(int i=2;i<=T+1;i++)
        scanf("%d",&a[i]);
    a[0]=A;a[1]=B;
    f[0]=0;
    int now=0,last=1; 
    for(int i=2;i<=T+1;i++)
        sum[i]=sum[i-1]+abs(a[i-1]-a[i]);
    g[0]=0;
    Root=1;tot++;
    t[1].key=Rand();
    t[1].val=a[0];
    t[1].big=g[0]-sum[1]+a[0];
    t[1].sma=g[0]-sum[1]-a[0]; 
    t[1].lch=t[1].rch=0;
    t[1].bh=0;
    for(int i=2;i<=T+1;i++){
        int x=1<<29,y=1<<29,z;
        split(Root,x,y,a[i]);
        f[i-1]=1ll<<50;
        if(x)
            f[i-1]=min(t[x].sma+a[i],f[i-1]);
        if(y)   
            f[i-1]=min(t[y].big-a[i],f[i-1]);
        f[i-1]+=sum[i-1];   
        g[i-1]=f[i-1]; 
        z=++tot;
        t[z].key=Rand();
        t[z].val=a[i-1];
        t[z].bh=i-1;
        t[z].big=g[i-1]-sum[i]+a[i-1];
        t[z].sma=g[i-1]-sum[i]-a[i-1]; 
        t[z].lch=t[z].rch=0;
        merge(Root,x,y);
        split(Root,x,y,a[i-1]);
        merge(x,x,z);
        merge(Root,x,y);
    }
    minl=1ll<<50;
    for(int i=0;i<=T;i++)
        minl=min(g[i]+sum[T+1]-sum[i+1],minl);
    cout<<minl;
    return 0;
}

E N D !

总结:第十名,主要是第3题没捞到44分,不然就第4的(don’t fake)

预期:203

加油,祝我 R a t i n g O v e r f l o w ! (don’t fake)

猜你喜欢

转载自blog.csdn.net/HQG_AC/article/details/81542177