zoukankan      html  css  js  c++  java
  • BZOJ4628 BJOI2016IP地址(trie)

      离线,每次修改相当于对该规则的所有匹配点的值+1,考虑在trie上打加法标记和匹配标记,匹配标记不下传,加法标记下传遇到匹配标记时清空。注意是用b时刻前缀-a时刻前缀,而不是(a-1)时刻前缀,具体我也不知道为啥可能是我没看懂题。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    #define N 100010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,cnt,ans[N],root;
    struct data{int ch[2],x,tag,lazy;
    }tree[N<<6];
    struct bit{int x,n,id;};
    struct data2{int op;bit ip;
    }q[N];
    bit gettwo()
    {
        unsigned int x=0,cnt=0;char c=getchar();
        while (c<'0'||c>'9') c=getchar();
        while (c>='0'&&c<='1') x+=(c^48)<<cnt,cnt++,c=getchar();
        return (bit){x,cnt};
    }
    vector<bit> INS[N],DEL[N];
    void update(int k,int x){if (!tree[k].tag) tree[k].x+=x,tree[k].lazy+=x;}
    void down(int k)
    {
        if (!tree[k].ch[0]) tree[k].ch[0]=++cnt;
        update(tree[k].ch[0],tree[k].lazy);
        if (!tree[k].ch[1]) tree[k].ch[1]=++cnt;
        update(tree[k].ch[1],tree[k].lazy);
        tree[k].lazy=0; 
    }
    void ins(int &k,bit x,int p)
    {
        if (!k) k=++cnt;
        if (p==x.n) {update(k,1),tree[k].tag++;return;}
        if (tree[k].lazy) down(k);
        ins(tree[k].ch[(x.x&(1<<p))>0],x,p+1);
    }
    void del(int &k,bit x,int p)
    {
        if (!k) k=++cnt;
        if (p==x.n) {tree[k].tag--,update(k,1);return;}
        if (tree[k].lazy) down(k);
        del(tree[k].ch[(x.x&(1<<p))>0],x,p+1);
    }
    int query(int k,bit x,int p)
    {
        if (!k) return 0;
        if (p==x.n) return tree[k].x;
        if (tree[k].lazy) down(k);
        return query(tree[k].ch[(x.x&(1<<p))>0],x,p+1);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4628.in","r",stdin);
        freopen("bzoj4628.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=n;i++)
        {
            char c=getc();if (c=='A') q[i].op=1;else q[i].op=-1;
            q[i].ip=gettwo();
        }
        for (int i=1;i<=m;i++)
        {
            bit x=gettwo();x.id=i;
            DEL[read()].push_back(x);
            INS[read()].push_back(x);
        }
        for (int i=1;i<=n;i++)
        {
            if (q[i].op==1) ins(root,q[i].ip,0);else del(root,q[i].ip,0);
            for (int j=0;j<INS[i].size();j++) ans[INS[i][j].id]+=query(root,INS[i][j],0); 
            for (int j=0;j<DEL[i].size();j++) ans[DEL[i][j].id]-=query(root,DEL[i][j],0);
            //for (int j=1;j<=cnt;j++) cout<<tree[j].ch[0]<<' '<<tree[j].ch[1]<<' '<<tree[j].x<<' '<<tree[j].tag<<' '<<tree[j].lazy<<endl;cout<<endl;
        }
        for (int i=1;i<=m;i++) printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    1065-两路合并
    1064-快速排序
    1063-冒泡排序
    1062-直接插入排序
    1061-简单选择排序
    1058-Tom and Jerry
    关于WinForm引用WPF窗体
    ref与out的区别
    看到他我一下子就悟了(续)---委托
    域名的a记录转过来他的公网ip
  • 原文地址:https://www.cnblogs.com/Gloid/p/10213792.html
Copyright © 2011-2022 走看看