2012天津现场赛

来源:互联网 发布:定额编号查询软件 编辑:程序博客网 时间:2024/04/30 07:31

这场去了天津现场,做的明显不如网赛来的顺利,感觉自己准备的很不充分啊,努力刷题吧~~

Str2int

用后缀自动机来搞。将给定的串用10这个字符连接起来,建一个SAM,然后按照节点代表的串长度bfs一下,来一个dp就可以求出答案了。

如果用SA来解,必须预处理后在O(1)的时间得到[l,r]区间的所有前缀和,蛋疼。

还是最简状态自动机简单些。明显状态和阶段都好了,dp一下就出来了,具体看代码。

#include<cstdio>#include<cstdlib>#include<queue>#include<vector>#include<string.h>using namespace std;const int MAX=410003;const int NUM=12;const char BASE='0';const int mod=2012;#define Endstruct node{    node* ch[NUM],*fa;    int len,hash,num;#ifdef End    int end;#endif    node(){}    node(node* father,int lenth)    {        fa=father;        len=lenth;        hash=0;num=0;#ifdef End        end=0;#endif        memset(ch,0,sizeof ch);    }}tree[MAX],*Root;int cnt;bool vis[MAX];void SAM(char* a,int n){    cnt=0;    memset(tree,0,sizeof(tree));    Root=tree+(cnt++);    *Root=node(0,0);    node *p=Root,*np,*op,*cp;    int i,idx;    for(i=0;i<n;++i)    {        idx=a[i]-BASE;        np=tree+(cnt++);        *np=node(0,i+1);        np->num=0;#ifdef End        np->end=i;#endif        while(p && !p->ch[idx])            p->ch[idx]=np,p=p->fa;        if(p && p->ch[idx])        {            op=p->ch[idx];            if(p->len+1==op->len)                np->fa=op;            else            {                cp=tree+(cnt++);                *cp=*op;                cp->num=0;#ifdef End                cp->end=i;#endif                cp->len=p->len+1;                op->fa=cp;np->fa=cp;                while(p && p->ch[idx]==op)                    p->ch[idx]=cp,p=p->fa;            }        }        else np->fa=Root;        p=np;    }}int n,m;char s[MAX];vector<node*> hh[MAX];int bfs(){    memset(vis,0,sizeof(vis));    int sum=0,idx,i,j;    Root->num=1;    for(i=0;i<=n;++i)      while (!hh[i].empty()) hh[i].clear();    for(i=0;i<cnt;++i)        hh[tree[i].len].push_back(tree+i);    for(i=0;i<=n;i++)        for(j=hh[i].size()-1;j>=0;--j)        {            if (!hh[i][j]->num) continue;            for (idx=0; idx<10; idx++)            {                if (hh[i][j]==Root && idx==0) continue;                if (hh[i][j]->ch[idx]){                    hh[i][j]->ch[idx]->hash+=                      hh[i][j]->hash*10+idx*hh[i][j]->num;                    hh[i][j]->ch[idx]->hash%=mod;                    hh[i][j]->ch[idx]->num+=hh[i][j]->num;                    sum+=hh[i][j]->hash*10+idx*hh[i][j]->num;                    sum%=mod;                }            }        }    return sum;}int main(){    int m,sum,i,len;    char *sp;    while ( ~scanf("%d",&m) )    {        memset(s,0,sizeof(s));        n=sum=0;        sp=s;        for (i=0; i<m; i++)        {            scanf("%s",sp);            len=strlen(sp);            sp+=len;            *(sp++)='0'+10;        }        *sp=0;        n=strlen(s);        SAM(s,n);        sum=bfs();        printf("%d\n",sum);    }    return 0;}

 

 

 

charge-station

简单贪心题。城市i的费用比所有小于i的城市费用和都高(这个在二进制下很容易看出来)。

所以先假设全部城市都建加油站,check()一下,不满足题意就puts("-1");

然后从高到低逐个删去城市,如果check()满足,那么果断删掉,如果出现不满足的情况,就不能删掉。重复此过程一直到第二个城市。

最后输出结果,为了方便题目叫我们直接输出二进制。

(-这么简单的题居然没做,低头....(-

#include<cstdio>#include<cstring>#include<cmath>const int N = 130;struct node{    int x,y;//maybe in double;}a[N];int n,d;int g[N][N];int distance(node &a, node &b){    int ret,dx,dy;    dx=a.x-b.x, dy=a.y-b.y;    ret=sqrt( dx*dx+dy*dy );    if (ret*ret == dx*dx + dy*dy) return ret;    else return ret+1;}bool vis[N];int q[N],ans[N];bool check(){    int i,head,tail,t;    memset(vis,0,sizeof(vis));    vis[0]=1, q[0]=0, head=1, tail=0;    while (tail<head){        t=q[tail++];        for (i=0; i<n; i++)          if (!vis[i]){            if (ans[i]){                if (g[t][i]<=d) {                    q[head++]=i, vis[i]=1;                    //printf("@%d %d\n",t,i);                }            }else{                if (g[t][i]+g[i][t]<=d) {                    vis[i]=1;                    //printf("@%d %d\n",t,i);                }            }          }    }    for (i=0; i<n; i++) if (vis[i]==0) return false;    return true;}void solve(){    int i;    for (i=0; i<n; i++) ans[i]=1;    if (!check()) {        puts("-1");        return ;    }    for (i=n-1; i>0; i--){        ans[i]=0;//assert        //printf("@erase:%d\n",i);        if (!check()) {            ans[i]=1;        }    }    i=n-1;    while (ans[i]==0) i--;    for (; i>=0; i--) if (ans[i]) printf("1");else printf("0");    puts("");}int main(){    int i,j;    while ( ~scanf("%d%d",&n,&d) ){        for (i=0; i<n; i++)          scanf("%d %d", &a[i].x, &a[i].y);        for (i=0; i<n; i++)          for (j=0; j<n; j++)            g[i][j]=distance(a[i],a[j]);        solve();    }    return 0;}


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

原创粉丝点击