HDU 4117

被安排的明明白白,一个调了四小时多的题目,最后发现区间更新不会,还把所有数据结构交给我,EXM???喵喵喵。今天七夕可以说是很惨了,I'm still loving you my dear "father" even if it can not be.

#include<cstdio>
#include<iostream>
#include<bitset>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#define mp make_pair
#define pb push_back
#define ll long long
#define lc no[x].ch[0]
#define rc no[x].ch[1]
#define pa no[x].fa
#define db double
#define ls x<<1
#define rs x<<1|1
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Forr(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=300010;
const int maxt=20010;
int n,m;
char str[maxn];
int ch[maxn][27],fail[maxn],fa[maxn],dfsn[maxn],ln[maxn],q[maxn],cc[maxt],opo[maxn],pos[maxn];
int fir[maxn],v[maxn*2],nxt[maxn*2];
int cnt,root,M,ts,pv;
int h,t;
void add_e(int a,int b)
{
    ++M;nxt[M]=fir[a];fir[a]=M;v[M]=b;
}
void add(int a,int b)
{
    add_e(a,b);add_e(b,a);
}
void insertt(char *s)
{
    int len=strlen(s);
    int cur=root;
    for(int i=0;i<len;i++)
    {
        int c=s[i]-'a';
        if(!ch[cur][c])
        {
            ch[cur][c]=++cnt;
            memset(ch[cnt],0,sizeof(ch[cnt]));
            fa[cnt]=cur;
        }
        cur=ch[cur][c];
    }
}
void build_f()
{
    h=t=0;fail[root]=root;
    for(int i=0;i<26;i++)
    {
        if(!ch[root][i])
        {
            ch[root][i]=root;continue;
        }
        fail[ch[root][i]]=root;
        q[t++]=ch[root][i];
    }
    while(h!=t)
    {
        int cur=q[h++];
        for(int i=0;i<26;i++)
        {
            if(!ch[cur][i])
            {
                ch[cur][i]=ch[fail[cur]][i];
            }
            else
            {
                fail[ch[cur][i]]=ch[fail[cur]][i];
                q[t++]=ch[cur][i];
            }
        }
    }
}
void dfs1(int x,int ff=0)
{
    dfsn[x]=++pv;
    for(int i=fir[x],kk=v[i];i;i=nxt[i],kk=v[i])
    {

        if(kk==ff)continue;
        dfs1(kk,x);
    }
    ln[x]=pv;  return;
}
struct node
{
    int laz,maxx;
}no[maxn<<2];
void push_up(int x)
{
    no[x].maxx=max(no[ls].maxx,no[rs].maxx);
}
void push_down(int x)
{
    if(no[x].laz)
    {
        no[ls].maxx=max(no[x].laz,no[ls].maxx);
        no[rs].maxx=max(no[x].laz,no[rs].maxx);
        no[ls].laz=max(no[x].laz,no[ls].laz);
        no[rs].laz=max(no[x].laz,no[rs].laz);
        no[x].laz=0;
    }
}
void build(int x,int l,int r)
{
    no[x].laz=0;
    no[x].maxx=0;
    if(l==r)
    {
        return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    push_up(x);
}
void update(int x,int l,int r,int L,int R,int val)
{
    if(L<=l&&r<=R)
    {
        no[x].maxx=max(no[x].maxx,val);
        no[x].laz=max(no[x].laz,val);
        return;
    }
    int mid=(l+r)>>1;
    push_down(x);
    if(L<=mid) update(ls,l,mid,L,R,val);
    if(R>mid) update(rs,mid+1,r,L,R,val);
    push_up(x);
}
int query(int x,int l,int r,int pl)
{
    if(l==r) return no[x].maxx;
    push_down(x);
    int mid=(l+r)>>1;
    if(pl<=mid) return query(ls,l,mid,pl);
    if(pl>mid) return query(rs,mid+1,r,pl);
    push_up(x);

}
int main()
{
    int t;
    scanf("%d",&t);
    int tot=0;
    while(t--)
    {
        cnt=0;
        root=0;
        memset(ch[0],0,sizeof(ch[0]));
        memset(fir,0,sizeof(fir));
        memset(fa,0,sizeof(fa));
        memset(fail,0,sizeof(fail));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s%d",str+pos[i-1],&cc[i]);
            insertt(str+pos[i-1]);
            pos[i]=pos[i-1]+strlen(str+pos[i-1]);
        }
        build_f();
        M=0,pv=0;
        for(int i=1;i<=cnt;i++)
        {
            add(fail[i],i);
        }
        dfs1(0,0);
        build(1,1,pv);
        int mx=0,tmp;
        for(int i=1;i<=n;i++)
        {
            tmp=0;
            int now=root;
            for(int j=pos[i-1];j<pos[i];j++)
            {
              now=ch[now][str[j]-'a'];
              tmp=max(tmp,query(1,1,pv,dfsn[now]));
            }
            mx=max(tmp+cc[i],mx);
            update(1,1,pv,dfsn[now],ln[now],tmp+cc[i]);
        }
        printf("Case #%d: %d\n",++tot,mx);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值