[Usaco2015 FEB Gold][2016-2-21]考试总结

第一题裸四方暴力,一直在想怎么用数据结构优化,期间想到了主席树套二维线段树,然而会爆空间,但是只要从上到下从左到右便可以只要主席树了,然后动态开点就是 O(n2logn) 的空间,还是对主席树不熟练啊,我毕竟是以前只写过一次的蒟蒻。
第二题AC自动机搞啊,裸裸的,然而我写了个 O(n2) 居然只超了两个点,考场上,下考后都自以为是 O(n) 。我果然是无脑工业狗,一看见就开始怒敲AC自动机。
第三题考虑陈丹琪分治,接下来便考虑如何快速求出一条直线是否切割了凸包。对于一个直线方程 Ax+By+C=0 和点 (x,y) ,如果把点代入方程大于0则在直线上方,小于0反之。问题便转化为了凸包上这些点的最大值和最小值是否同号。
由于上下凸壳的函数值均为单峰函数,考虑三分即可。
此题我调了TM好久,三个错误:
一、以为上凸壳的函数就是上凸的,下凸壳的函数就是下凸的,导致三分挂掉;
二、判断同号时直接相乘判断正负,爆LL;
三、三分的复杂度是以1.5为底的,一个for循环for20遍少了。

#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cassert>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<climits>
#define X first
#define Y second
#define DB double
#define MP make_pair
#define LL long long
#define pb push_back
#define sqr(_) ((_)*(_))
#define INF 0x3f3f3f3f
#define pii pair<int,int>
#define pdd pair<DB,DB>
#define ull unsigned LL
#define zqf 1000000007
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
const int MAXN=751*751;
int n,m,k,T[MAXN],st[10000001],top=0,q,v,cnt;
int dp[751][751],sum[750],w[751][751],lc[10000001],rc[10000001],Sum[10000001];
void Read(int& x)
{
    x=0;char c;int flag=0;
    while(c=getchar())
    {
        if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;
        else if(flag)break;
    }
}
void insert(int& root,int l,int r)
{
    cnt++;
    if(!root)
        root=st[--top];
    if(l==r)
    {
        Sum[root]=(Sum[root]+v)%zqf;
        return;
    }
    int mid=(l+r)>>1;
    if(q<=mid)
        insert(lc[root],l,mid);
    else
        insert(rc[root],mid+1,r);
    Sum[root]=(Sum[lc[root]]+Sum[rc[root]])%zqf;
}
int query(int now,int l,int r)
{
    cnt++;
    if(!now)return 0;
    if(l>=1&&r<=q)
    {
        return Sum[now];
    }
    int mid=(l+r)>>1,a=0;
    if(1<=mid)
        a=(a+query(lc[now],l,mid))%zqf;
    if(q>mid)
        a=(a+query(rc[now],mid+1,r))%zqf;
    return a;
}
int main()
{
    freopen("hopscotch.in","r",stdin);
    freopen("hopscotch.out","w",stdout);
    for(int i=0;i<7000000;i++)st[++top]=i+1;
    Read(n);Read(m);Read(k);
    dp[1][1]=1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            Read(w[i][j]);
    for(int i=2;i<=n;i++)
    {
        int SUM=0;
        for(int j=2;j<=m;j++)
        {
            if(i==3&&j==4)
                i=3;
            sum[j-1]=(sum[j-1]+dp[i-1][j-1])%zqf;
            SUM=(sum[j-1]+SUM)%zqf;
            q=j-1;v=dp[i-1][j-1];cnt=0;
            insert(T[w[i-1][j-1]],1,m);
            cnt=0;
            dp[i][j]=(SUM-query(T[w[i][j]],1,m))%zqf;
            if(dp[i][j]<0)dp[i][j]=(dp[i][j]+zqf)%zqf;
        }
    }
    printf("%d\n",dp[n][m]);
}
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cassert>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<climits>
#define X first
#define Y second
#define DB double
#define MP make_pair
#define LL long long
#define pb push_back
#define sqr(_) ((_)*(_))
#define INF 0x3f3f3f3f
#define pii pair<int,int>
#define pdd pair<DB,DB>
#define ull unsigned LL
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
const int MAXN=2e5;
int n,match[MAXN],flag=0,next[MAXN],from[MAXN],jg=0,M,st[MAXN],top;
char s[MAXN],tmp[MAXN];
struct ACM{
    int son[MAXN][27],f[MAXN],last[MAXN],val[MAXN],tot,Len[MAXN];
    ACM(){
        memset(son,0,sizeof(son));
        memset(f,0,sizeof(f));
        memset(last,0,sizeof(last));
        memset(val,0,sizeof(val));
        tot=0;
    }
    int idx(char c)
    {
        return c-'a';
    }
    void insert(char* S)
    {
        int m=strlen(S+1),u=0;
        for(int i=next[0];i<=m;i=next[i])
        {
            int v=idx(S[i]);
            if(!son[u][v])
                son[u][v]=++tot;
            u=son[u][v];
        }
        val[u]=1;
        Len[u]=m;
    }
    void getFail()
    {
        queue<int> q;
        for(int i=0;i<26;i++)
        {
            if(son[0][i])
            {
                q.push(son[0][i]);
                f[son[0][i]]=last[son[0][i]]=0;
            }
        }
        while(!q.empty())
        {
            int r=q.front();q.pop();
            for(int i=0;i<26;i++)
            {
                int u=son[r][i];
                if(!u){son[r][i]=son[f[r]][i];continue;}
                q.push(u);
                int j=f[r];
                while(j&&!son[j][i])j=f[j];
                f[u]=son[j][i];
                last[u]=val[f[u]]?f[u]:last[f[u]];
            }
        }
    }
    void update(int& now,int l,int& p)
    {
        int cnt=1,o=now,fuck=0;
        while(1)
        {
            ++fuck;
            //DEBUG("%d\n",fuck);
            if(cnt==l)
            {
                match[now]=o;
                match[o]=now;
                break;
            }
            now=from[now];
            cnt++;
            p=st[--top];
        }
        next[from[now]]=next[o];
        from[next[o]]=from[now];
        now=from[now];
        p=st[--top];
    }
    void find(char* S)
    {
        ++jg;
        //if(jg%10000==0)DEBUG("%d\n",jg);
        int j=0,cnt=0;
        top=0;
        st[++top]=j;
        for(int i=next[0];i<=M;i=next[i])
        {
            ++cnt;
            //DEBUG("%d\n",cnt);
            int v=idx(S[i]);
            j=son[j][v];
            st[++top]=j;
            if(val[j])
            {
                flag=1;
                update(i,Len[j],j);
            }
        }
    }
}Ac;
int main()
{
    freopen("censor.in","r",stdin);
    freopen("censor.out","w",stdout);
    memset(match,-1,sizeof(match));
    scanf("%s",s+1);
    M=strlen(s+1);
    for(int i=0;i<MAXN;i++)next[i]=i+1,from[i]=i-1;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",tmp+1);
        Ac.insert(tmp);
    }
    Ac.getFail();
    while(1)
    {   
        Ac.find(s);
        if(!flag)break;
        flag=0;
    }
    for(int i=next[0];i<=M;i=next[i])
        putchar(s[i]);
    puts("");
}
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cassert>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<climits>
#define X first
#define Y second
#define DB double
#define MP make_pair
#define LL long long
#define pb push_back
#define sqr(_) ((_)*(_))
#define INF 0x3f3f3f3f
#define int LL
#define pii pair<int,int>
#define pdd pair<DB,DB>
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
const int MAXN=3e5;
struct op{
    int t,a,b,c;
    op(int t=0,int a=0,int b=0,int c=0):t(t),a(a),b(b),c(c){}
}oper[MAXN];
template<typename T> void Read(T& x)
{
    x=0;int flag=0,sgn=1;char c;
    while(c=getchar())
    {
        if(c=='-')sgn=-1;
        else if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;
        else if(flag)break;
    }
    x*=sgn;
}
int n,ans[MAXN],tot=0,p,q;
bool cant[MAXN];
pii pot[MAXN],ch[MAXN];
int cross(const pii& a,const pii& b)
{
    return a.X*b.Y-a.Y*b.X;
}
pdd operator -(const pii& a,const pii& b)
{
    return MP(a.X-b.X,a.Y-b.Y);
}
void CovHull(int l,int r)
{
    p=q=0;
    sort(pot,pot+tot);
    for(int i=0;i<tot;i++){
        while(p>1&&cross(ch[p-1]-ch[p-2],pot[i]-ch[p-2])<=0)p--;
        ch[p++]=pot[i];
    }
    q=p;
    for(int i=tot-2;i>=0;i--){
        while(p>q&&cross(ch[p-1]-ch[p-2],pot[i]-ch[p-2])<=0)p--;
        ch[p++]=pot[i];
    }
    p--;
}
int sgn(int x)
{
    return x<0?-1:1;
}
int F(int id,pii P)
{
    return oper[id].a*P.X+oper[id].b*P.Y+oper[id].c;
}
int UPgetmax(int id,int ql,int qr)
{
    int l=ql,r=qr;
    if(qr<ql)return -INF;
    for(int i=1;i<=25;i++)
    {
        int m1=l+(r-l+1)/3,
            m2=r-(r-l+1)/3;
        if(F(id,ch[m1])>F(id,ch[m2]))
            r=m2;
        else
            l=m1;
    }
    return max(F(id,ch[r]),F(id,ch[l]));
}
int Cgetmax(int id,int ql,int qr)
{
    if(ql>qr)
        return -INF;
    int l=ql,r=qr;
    return max(F(id,ch[r]),F(id,ch[l]));
}
int DOWNgetmin(int id,int ql,int qr)
{
    int l=ql,r=qr;
    if(qr<ql)return INF;
    for(int i=1;i<=25;i++)
    {
        int m1=l+(r-l+1)/3,
            m2=r-(r-l+1)/3;
        if(F(id,ch[m1])<F(id,ch[m2]))
            r=m2;
        else
            l=m1;
    }
    return min(F(id,ch[r]),F(id,ch[l]));
}
int Cgetmin(int id,int ql,int qr)
{
    if(ql>qr)return INF;
    return min(F(id,ch[ql]),F(id,ch[qr]));
}
void _cdq_Div_Con(int l,int r)
{
    if(l==r)return;
    int mid=(l+r)>>1;
    tot=0;
    for(int i=l;i<=mid;i++)
        if(oper[i].t==1)
            pot[tot++]=MP(oper[i].a,oper[i].b);
    CovHull(l,r);
    if(tot==0)
    {
        _cdq_Div_Con(mid+1,r);
        return;
    }
    for(int i=mid+1;i<=r;i++)
    if(oper[i].t==2&&!cant[i])
    {
        int mx=max(max(UPgetmax(i,0,q-1),Cgetmax(i,0,q-1)),max(UPgetmax(i,q,p-1),Cgetmax(i,q,p-1))),
            mn=min(min(Cgetmin(i,0,q-1),DOWNgetmin(i,0,q-1)),min(DOWNgetmin(i,q,p-1),Cgetmin(i,q,p-1)));
        if(ans[i]!=0)
            if(mx==0||mx==0||sgn(mx)!=sgn(mn)||sgn(mx)!=sgn(ans[i]))
                cant[i]=1;
        if(mx==0||mn==0||sgn(mx)*sgn(mn)<0)cant[i]=1;
        ans[i]=sgn(mx);
    }
    _cdq_Div_Con(l,mid);
    _cdq_Div_Con(mid+1,r);
}   
main()
{
#ifndef ONLINE_JUDGE
    freopen("fencing.in","r",stdin);
    freopen("fencing.out","w",stdout);
#endif
    Read(n);Read(q);
    for(int i=1;i<=n;i++)
    {
        int a,b;
        Read(a);Read(b);
        oper[i]=op(1,a,b,0);
    }
    for(int i=1;i<=q;i++)
    {
        int a,b,c,d;
        Read(a);
        if(a==1)
        {
            Read(b);Read(c);
            oper[n+i]=op(a,b,c,0);
        }
        else
        {
            Read(b);Read(c);Read(d);
            oper[n+i]=op(a,b,c,-d);
        }
    }
    n+=q;
    _cdq_Div_Con(1,n);
    for(int i=1;i<=n;i++)
        if(oper[i].t==2)
        {
            if(!cant[i])
                puts("YES");
            else
                puts("NO");
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值