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; }