zoukankan      html  css  js  c++  java
  • HDU 5845 Best Division

    $dp$,字典树。

    $dp$递推式很容易知道。dp[i]=max{dp[j]+1} a[j]^..^a[i]<=X,并且$[j,i]$长度不能超过$L$。

    但是暴力来复杂度极高,所以需要用字典树维护这个东西。将前缀异或和插入到字典树中,然后不断维护$a[i]$位置之前$L$个前缀异或和就好了。

    跑了$405ms$,第一次排到第一,有点激动~~~

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-8;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    template <class T>
    inline void read(T &x)
    {
        char c = getchar(); x = 0;while(!isdigit(c)) c = getchar();
        while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar();  }
    }
    
    const LL mod=(LL)268435456;
    const int maxn=100010;
    LL a[maxn],X,P,Q;
    int T,n,L,dp[maxn],h;
    struct Node { int cnt,mx,nx[2]; }s[33*maxn];
    int sz; bool fail,f[maxn];
    
    int add()
    {
        s[sz].mx=0; s[sz].cnt=0;
        s[sz].nx[0]=s[sz].nx[1]=-1; sz++;
        return sz-1;
    }
    
    void Delete(LL num)
    {
        int p=0;
        for(int i=31;i>=0;i--)
        {
            int x; LL g=(LL)(1<<i); if(num&g) x=1; else x=0;
            int t=p; p=s[p].nx[x]; s[p].cnt--;
            if(s[p].cnt==0) { s[t].nx[x]=-1; return; }
        }
    }
    
    void Insert(LL num,int val)
    {
        int p=0;
        for(int i=31;i>=0;i--)
        {
            int x; LL g=(LL)(1<<i); if(num&g) x=1; else x=0;
            if(s[p].nx[x]==-1) s[p].nx[x]=add();
            p=s[p].nx[x]; s[p].cnt++; s[p].mx=max(s[p].mx,val);
        }
    }
    
    void Find(LL num)
    {
        int p=0;
        for(int i=31;i>=0;i--)
        {
            int x; LL g=(LL)(1<<i); if(num&g) x=1; else x=0;
            int y; if(X&g) y=1; else y=0;
    
            if(y==0)
            {
                p=s[p].nx[x]; if(p==-1) return;
                if(i==0) h=max(h,s[p].mx),fail=0;
            }
            else
            {
                if(s[p].nx[x]!=-1) h=max(h,s[s[p].nx[x]].mx),fail=0;
                p=s[p].nx[x^1]; if(p==-1) return;
                if(i==0) h=max(h,s[p].mx),fail=0;
            }
        }
    }
    
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%lld%d",&n,&X,&L);
            scanf("%lld%lld%lld",&a[1],&P,&Q);
            for(int i=2;i<=n;i++) a[i]=(a[i-1]*P%mod+Q)%mod;
    
            sz=0; s[sz].cnt=0; s[sz].nx[0]=s[sz].nx[1]=-1; sz++;
    
            for(int i=1;i<=n;i++) f[i]=0;
            for(int i=1;i<=n;i++)
            {
                if(i-L-1>=1&&f[i-L-1] ) Delete(a[i-L-1]);
                dp[i]=0; a[i]=a[i]^a[i-1]; if(a[i]<=X) dp[i]=1;
                h=0; fail=1; Find(a[i]); if(fail==0) dp[i]=h+1;
                if(dp[i]!=0) { Insert(a[i],dp[i]); f[i]=1; }
            }
    
            printf("%d
    ",dp[n]);
        }
        return 0;
    }
  • 相关阅读:
    《代码阅读与实践》阅读笔记*part1
    HDFS JAVA API
    《需求工程》阅读笔记*part3
    《需求工程》阅读笔记*part2
    HDFS文件命令
    HOG特征+SVM行人检测
    winchecksec安装踩坑
    加壳:挂起方式创建进程
    内存写入注入
    远程线程注入
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5789757.html
Copyright © 2011-2022 走看看