【BJOI2016】IP地址
追不到北京的神仙小姐姐(话说北京的神仙小姐姐长的好像我女神啊,不知道她去P了还是去T了呢),我只能颓废做北京省选了。。。。。。
咳咳,上面那句话不能让我女神看到。
题面
https://www.luogu.org/problem/P5460
题解
$[l,r]$变换了多少次等价于$[1,r]$-$[1,l-1]$,所以把所有的询问看成两个时间,离线处理。
把$trie$树看成线段树,相当于区间修改,单点查询。下传标记时,如果下面原来有标记,则失效。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; struct node{ int ch[2],opt,add,v; } trie[3200050]; struct question{ int loc,time,ans,id; bool operator < (const question rhs) const { return time<rhs.time; } } a[200050]; bool cmp(question a,question b){ return a.id<b.id; } int n,q,cnt; char s[100050][5],x[100050][35],qes[100050][35]; void insert(int x,char *p) { if (*p=='\0') return; if (!trie[x].ch[*p-'0']) { trie[x].ch[*p-'0']=++cnt; insert(cnt,p+1); } else insert(trie[x].ch[*p-'0'],p+1); } int find(int x,char *p) { if (*p=='\0') return x; if (!trie[x].ch[*p-'0']) return x; else return find(trie[x].ch[*p-'0'],p+1); } void pushdown(int now){ int k=trie[now].add; if (trie[now].ch[0] && !trie[trie[now].ch[0]].opt) trie[trie[now].ch[0]].v+=k,trie[trie[now].ch[0]].add+=k; if (trie[now].ch[1] && !trie[trie[now].ch[1]].opt) trie[trie[now].ch[1]].v+=k,trie[trie[now].ch[1]].add+=k; trie[now].add=0; } int cha(int now,int x,char *p){ if (trie[now].add!=0) pushdown(now); if (now==x) return trie[now].v; return cha(trie[now].ch[*p-'0'],x,p+1); } void change(int now,int x,char *p){ if (trie[now].add!=0) pushdown(now); if (now==x) { trie[now].v++; trie[now].add++; return; } change(trie[now].ch[*p-'0'],x,p+1); } int main(){ int i,j,lb,rb,locb; scanf("%d %d",&n,&q); cnt=0; for (i=1;i<=n;i++) { scanf("%s %s",s[i],x[i]); insert(0,x[i]); } cnt=0; for (i=1;i<=q;i++) { scanf("%s %d %d",qes[i],&lb,&rb); locb=find(0,qes[i]); a[++cnt]=(question){locb,lb,0,2*i-1}; a[++cnt]=(question){locb,rb,0,2*i}; } sort(a+1,a+cnt+1); j=1; for (i=1;i<=n;i++) { int now=find(0,x[i]); change(0,now,x[i]); //trie[now].v++; //trie[now].add++; if (s[i][0]=='D') trie[now].opt=0; else if (s[i][0]=='A') trie[now].opt=1; for (;a[j].time==i && j<=cnt;j++) a[j].ans=cha(0,a[j].loc,qes[(a[j].id+1)/2]); } sort(a+1,a+cnt+1,cmp); for (i=1;i<=q;i++) { printf("%d\n",a[2*i].ans-a[2*i-1].ans); } }