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\n";
#else
    const char LL[]="%lld\n";
#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\n",ans[i]);
    return 0;
}

 

posted @ 2019-01-04 13:11  Gloid  阅读(364)  评论(0编辑  收藏  举报