补题(2016-2017区域赛)

写在前面:
有些事很艰难,但必须去做。
比如模拟以前经历过的困境,尝试再次置身其中。
假如连过去的问题都无法解决,又凭什么让自己相信,当全新的问题出现时,能做得更好呢?

2016 ICPC Dalian, by Avalon
Board: http://board.acmicpc.info/icpc2016/dlmu_onsite.php
Solved Now: 10/11

Problem B
http://acm.hdu.edu.cn/showproblem.php?pid=5972
Code:

#include <bits/stdc++.h>
using namespace std;
int n;
bitset<1003>b[10];
char s[5000003];
int main(){
    while(~scanf("%d",&n)){
        for(int i=0;i<10;i++)b[i].reset();
        for(int i=0;i<n;i++){
            int k;
            scanf("%d",&k);
            for(int j=0;j<k;j++){
                int x;
                scanf("%d",&x);
                b[x].set(i);
            }
        }
        fread(s,1,5000001,stdin);
        int m=strlen(s);
        bitset<1003>ans;
        for(int i=0;i<m;i++){
            ans<<=1;
            ans.set(0);
            ans&=b[s[i]-'0'];
            if(ans[n-1]){
                fwrite(s+i-n+1,1,n,stdout);
                putchar('\n');
            }
        }
    }
}

Key: BITSET Shift-And FastIO

Problem K
http://acm.hdu.edu.cn/showproblem.php?pid=5981
Code:

#include <bits/stdc++.h>
using namespace std;
const int mod=100000073;
typedef long long ll;
ll dp[5000003];
ll sum[5000003];
int main(){
    dp[1]=1;dp[2]=2;
    sum[1]=1;sum[2]=3;
    int l=1,r=1;
    for(int i=3;i<=5000000;i++){
        while(dp[l+1]+l+1<=i-1)l++;
        dp[i]=i-l;
        while(dp[r+1]<=dp[i]-1)r++;
        sum[i]=sum[r]-sum[l-1]+sum[i-1]+mod;
        while(sum[i]>mod)sum[i]-=mod;
    }
    int x,y;
    while(~scanf("%d%d",&x,&y)){
        x=y-x+1;
        printf("%lld %lld\n",dp[x],(sum[x]-sum[x-1]+mod)%mod);
    }
}

Key: DP 2-Pointer

2016 ICPC Qingdao, by Avalon
No Official Board
Replay Board: https://vjudge.net/contest/142308#rank
Solved Now: 6/13

Problem K
http://acm.hdu.edu.cn/showproblem.php?pid=5992
Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=1ll<<60;
struct node{
    int d[3],ma[3],mi[3],l,r,id;
}T[200003];
int rt,n,m,cmp_d;
inline bool cmp(node a,node b){
    return a.d[cmp_d]<b.d[cmp_d];
}
inline void up(int u,int v){
    T[u].ma[0]=max(T[u].ma[0],T[v].ma[0]);
    T[u].ma[1]=max(T[u].ma[1],T[v].ma[1]);
    T[u].ma[2]=max(T[u].ma[2],T[v].ma[2]);
    T[u].mi[0]=min(T[u].mi[0],T[v].mi[0]);
    T[u].mi[1]=min(T[u].mi[1],T[v].mi[1]);
    T[u].mi[2]=min(T[u].mi[2],T[v].mi[2]);
}
inline int build(int l,int r,int D){
    int mid=(l+r)>>1;
    cmp_d=D;
    nth_element(T+l,T+mid,T+r+1,cmp);
    T[mid].ma[0]=T[mid].mi[0]=T[mid].d[0];
    T[mid].ma[1]=T[mid].mi[1]=T[mid].d[1];
    T[mid].ma[2]=T[mid].mi[2]=T[mid].d[2];

    if(l!=mid){
        T[mid].l=build(l,mid-1,(D+1)%3);
        up(mid,T[mid].l);
    }
    if(r!=mid){
        T[mid].r=build(mid+1,r,(D+1)%3);
        up(mid,T[mid].r);
    }
    return mid;
}

ll dis;
int ans;
int x,y,c;
//估计范围
inline ll getdis(int p){
    ll ret=0;
    if(T[p].mi[2]>c)return INF;
    if(x>T[p].ma[0])ret+=1ll*(x-T[p].ma[0])*(x-T[p].ma[0]);
    if(x<T[p].mi[0])ret+=1ll*(T[p].mi[0]-x)*(T[p].mi[0]-x);
    if(y>T[p].ma[1])ret+=1ll*(y-T[p].ma[1])*(y-T[p].ma[1]);
    if(y<T[p].mi[1])ret+=1ll*(T[p].mi[1]-y)*(T[p].mi[1]-y);
    return ret;
}
inline void query(int p){
    ll d0=1ll*(x-T[p].d[0])*(x-T[p].d[0])+1ll*(y-T[p].d[1])*(y-T[p].d[1]);
    if(T[p].d[2]>c)d0=INF;
    if(d0<dis||(d0==dis&&T[p].id<T[ans].id)){
        dis=d0;
        ans=p;
    }
    ll dl=INF,dr=INF;
    if(T[p].l)dl=getdis(T[p].l);
    if(T[p].r)dr=getdis(T[p].r);
    if(dl<dr){
        if(dl<=dis)query(T[p].l);
        if(dr<=dis)query(T[p].r);
    }
    else {
        if(dr<=dis)query(T[p].r);
        if(dl<=dis)query(T[p].l);
    }
}
int main(){
    int tt;
    scanf("%d",&tt);
    while(tt--){
        memset(T,0,sizeof(T));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&T[i].d[0],&T[i].d[1],&T[i].d[2]);
            T[i].id=i;
        }
        rt=build(1,n,0);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&c);
            ans=0;
            dis=INF;
            query(rt);
            printf("%d %d %d\n",T[ans].d[0],T[ans].d[1],T[ans].d[2]);
        }
    }
}

Key: KD-Tree
Referred to:
https://blog.csdn.net/jiangshibiao/article/details/34144829

2016 ICPC China-Final, by Avalon
Board: http://codeforces.com/gym/101194/standings
Solved Now: 8/13

Problem G
http://codeforces.com/gym/101194/attachments/download/5009/20162017-acmicpc-china-final-en.pdf
Code:

#include <bits/stdc++.h>
using namespace std;
int n,m,q;
int a[200003];
int f[200003];
int siz[200003];
int fa[200003][20];
int fal[200003][20];
int ms[200003];
int tot;
int tim[200003];
int mx;
set<int>st[100003];
int tmp;
int ans[200003];
bool vis[200003];
struct edge{
    int u,v,w;
}rec[200003];
bool cmp(edge a,edge b){
    return a.w<b.w;
}
struct Edge{
    int to,next;
}e[400003];
int head[200003];
int cnt;
void add(int u,int v){
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}

int getfa(int u){
    if(f[u]==0)return u;
    return f[u]=getfa(f[u]);
}
void Union(int u,int v,int w){
    u=getfa(u);
    v=getfa(v);
    if(u==v)return ;
    tot++;
    add(tot,u);
    add(tot,v);
    f[u]=tot;
    f[v]=tot;
    fa[u][0]=tot;
    fa[v][0]=tot;
    fal[u][0]=w;
    fal[v][0]=w;
}
void dfs(int u){
    siz[u]=true;
    vis[u]=true;
    ms[u]=-1;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        if(vis[v])continue;
        dfs(v);
        siz[u]+=siz[v];
        if(ms[u]==-1||siz[ms[u]]<siz[v])ms[u]=v;
    }
}
void add(int u){
    if(a[u]==-1)return;
    int p=++tim[a[u]];
    if(p==1){
        st[p].insert(a[u]);
    }
    else {
        st[p-1].erase(a[u]);
        st[p].insert(a[u]);
    }
    if(p>mx){
        mx=p;
        tmp=a[u];
    }
    else if(p==mx){
        tmp=min(tmp,a[u]);
    }
}
void del(int u){
    if(a[u]==-1)return ;
    int p=--tim[a[u]];
    if(p==0){
        st[p+1].erase(a[u]);
    }
    else {
        st[p+1].erase(a[u]);
        st[p].insert(a[u]);
    }
    if(st[mx].empty()){
        --mx;
        if(mx==0)tmp=0;
        else tmp=*(st[mx].begin());
    }
}
void addtree(int u){
    add(u);
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        addtree(v);
    }
}
void deltree(int u){
    del(u);
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        deltree(v);
    }
}
void dfs2(int u){
    vis[u]=true;
    if(ms[u]==-1){
        add(u);
        ans[u]=tmp;
        return;
    }
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        if(v==ms[u])continue;
        dfs2(v);
        deltree(v);
    }
    dfs2(ms[u]);
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        if(v==ms[u])continue;
        addtree(v);
    }
    add(u);
    ans[u]=tmp;
}
void init(){
    memset(a,-1,sizeof(a));
    memset(f,0,sizeof(f));
    tot=n;
    cnt=0;
    memset(head,-1,sizeof(head));
    memset(fa,0,sizeof(fa));
    mx=0;
    for(int i=1;i<=n;i++)st[i].clear();
}
void printtree(){
    for(int i=1;i<=tot;i++)printf("%d%c",a[i],i==tot?'\n':' ');
    for(int u=1;u<=tot;u++){
        for(int i=head[u];~i;i=e[i].next){
            int v=e[i].to;
            cout<<u<<' '<<v<<' '<<fal[v]<<endl;
        }
    }
}
void printans(){
    for(int i=1;i<=tot;i++){
        printf("%d %d\n",i,ans[i]);
    }
}
void debug(){
    printtree();
    printans();
}
int main(){
    int T;
    scanf("%d",&T);
    for(int tt=1;tt<=T;tt++){
        scanf("%d%d",&n,&m);
        init();
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            rec[i]=(edge){u,v,w};
        }
        sort(rec+1,rec+1+m,cmp);
        for(int i=1;i<=m;i++){
            Union(rec[i].u,rec[i].v,rec[i].w);
        }
        memset(vis,false,sizeof(vis));
        for(int i=tot;i>=1;i--){
            if(!vis[i]){
                dfs(i);
            }
        }
        memset(vis,false,sizeof(vis));
        for(int i=tot;i>=1;i--){
            if(!vis[i]){
                dfs2(i);
                deltree(i);
            }
        }
        memset(vis,false,sizeof(vis));
        for(int j=1;j<=18;j++){
            for(int i=1;i<=tot;i++){
                fa[i][j]=fa[fa[i][j-1]][j-1];
                fal[i][j]=fal[fa[i][j-1]][j-1];
            }
        }
        int q;
        scanf("%d",&q);
        printf("Case #%d:\n",tt);
        int last=0;
        while(q--){
            int x,y;
            scanf("%d%d",&x,&y);
            x^=last;
            y^=last;
            for(int j=18;j>=0;j--){
                if(fa[x][j]==0)continue;
                if(fal[x][j]<=y)x=fa[x][j];
            }
            last=ans[x];
            printf("%d\n",last);
        }
    }
}

Key: MST 启发式合并 树上倍增
只有补了题才知道自己有多菜

Problem F
http://codeforces.com/gym/101194/attachments/download/5009/20162017-acmicpc-china-final-en.pdf
Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=305000;
char str[maxn];
int s[maxn];
int sa[maxn], t[maxn], t2[maxn], c[maxn], n;
int Rank[maxn], height[maxn];
int u[maxn], d[maxn];
void build_sa(int m, int n){
    int i, *x=t, *y=t2;
    for(i=0;i<m;i++)c[i]=0;
    for(i=0;i<n;i++)c[x[i]=s[i]]++;
    for(i=1;i<m;i++)c[i]+=c[i-1];
    for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    for(int k=1;k<=n;k<<=1){
        int p=0;
        for(i=n-k;i<n;i++)y[p++]=i;
        for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
        for(i=0;i<m;i++)c[i]=0;
        for(i=0;i<n;i++)c[x[y[i]]]++;
        for(i=1;i<m;i++)c[i]+=c[i-1];
        for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
        swap(x, y);
        p=1;x[sa[0]]=0;
        for(i=1;i<n;i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
        if(p>=n)break;
        m=p;
    }
}
void geth(int n){
    int i, j, k=0;
    for(i=0;i<n;i++)Rank[sa[i]]=i;
    for(i=0;i<n;i++){
        if(k)k--;
        if(Rank[i]==0)break;
        j=sa[Rank[i]-1];
        while(s[i+k]==s[j+k])k++;
        height[Rank[i]]=k;
    }
}
int main()
{
    int T;
    scanf("%d", &T);
    for(int t=1;t<=T;t++){
        int q;
        scanf("%d", &q);
        n=0;
        int f1=0;
        for(int i=1;i<=q;i++){
            scanf("%s", str);
            int len=strlen(str);
            for(int j=0;j<len;j++){
                s[n++]=str[j]-'a'+1;
            }
            if(i==1){
                f1=len;
                s[n++]=30;
            }
            else s[n++]=0;
        }
        build_sa(31, n);
        geth(n);
        int l, r;
        int st=-1;
        int len=n;
        for(int i=1;i<n;i++){
            if(sa[i]>=f1)continue;
            l=i, r=i;
            while(sa[r]<f1)r++;
            u[l]=height[l];
            for(int j=l+1;j<r;j++)u[j]=min(height[j], u[j-1]);
            d[r-1]=height[r];
            for(int j=r-2;j>=l;j--)d[j]=min(height[j+1], d[j+1]);
            for(int j=l;j<r;j++){
                int M=max(u[j], d[j]);
                if(M+1<=f1-sa[j]&&M+1<len){
                    len=M+1;
                    st=sa[j];
                }
            }
            i=r;
        }
        printf("Case #%d: ", t);
        if(st==-1)printf("Impossible\n");
        else {
            for(int i=0;i<len;i++)printf("%c", s[st+i]+'a'-1);
            printf("\n");
        }
    }
}

Key: SA

猜你喜欢

转载自blog.csdn.net/MrBird_to_fly/article/details/80875472
今日推荐