[主席树维护HASH && SET维护DFS序] Codechef. Walks on the binary tree
来源:互联网 发布:七个魂器都是什么 知乎 编辑:程序博客网 时间:2024/05/17 07:26
传送门
每次加一个串 x 会增加 n-max{LCP(x,i)},因为是树上,max{LCP(x,i)}就肯定是dfs序中跟它相邻的点,也就是它们的lca深度最深。
那么就用set维护一下dfs序,比较的话,用主席树维护hash
#include <cstdio>#include <iostream>#include <algorithm>#include <set>#include <cstring>#include <string>#define fi first#define se secondusing namespace std;typedef unsigned long long ll;typedef pair<ll,ll> pari;const int N=100010,P1=1e9+7,P2=1e9+9;const pari base={7,29};int n,q,t,cnt,g,rt[N*50],ls[N*50],rs[N*50],tag[N*50],tot[N*50];pari pw[N],v[N*50],p[N];pari operator +(const pari &a,const pari &b){ return pari((a.fi+b.fi)%P1,(a.se+b.se)%P2); }pari operator -(const pari &a,const pari &b){ return pari((a.fi+P1-b.fi)%P1,(a.se+P2-b.se)%P2); }pari operator *(const pari &a,const pari &b){ return pari((a.fi*b.fi)%P1,(a.se*b.se)%P2); }inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void rea(int &x){ char c=nc(); x=0; for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());}inline void set1(int &g,int l,int r){ int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; tot[g]=tot[k]; v[g]=v[k]; tot[g]=r-l+1; v[g]=p[r-l]; tag[g]=1;}inline void set0(int &g,int l,int r){ int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; tot[g]=tot[k]; v[g]=v[k]; tot[g]=0; v[g]={0,0}; tag[g]=0;}inline void Push(int &g,int L,int R){ if(~tag[g]){ int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; tot[g]=tot[k]; v[g]=v[k]; int mid=L+R>>1; if(tag[g]) set1(ls[g],L,mid),set1(rs[g],mid+1,R); else set0(ls[g],L,mid),set0(rs[g],mid+1,R); tag[g]=-1; }}inline bool cmp(int &a,int &b,int l,int r){ Push(a,l,r); Push(b,l,r); if(l==r) return v[a]<v[b];; int mid=l+r>>1; if(v[ls[a]]==v[ls[b]]) return cmp(rs[a],rs[b],mid+1,r); else return cmp(ls[a],ls[b],l,mid);}struct u{ int x; friend bool operator ==(u a,u b){ return v[a.x]==v[b.x]; } friend bool operator <(u a,u b){ if(v[a.x]==v[b.x]) return false; return cmp(a.x,b.x,1,n); }};set<u> S;long long ans;int Find(int &g,int l,int r,int L,int R){ if(!g) return r; if(L==R) return tot[g]?-1:L; int mid=L+R>>1; Push(g,L,R); if(l==L && r==R){ if(tot[rs[g]]!=R-mid) return Find(rs[g],mid+1,r,mid+1,R); return Find(ls[g],l,mid,L,mid); } if(r<=mid) return Find(ls[g],l,r,L,mid); else if(l>mid) return Find(rs[g],l,r,mid+1,R); int ret=Find(rs[g],mid+1,r,mid+1,R); if(~ret) return ret; return Find(ls[g],l,mid,L,mid);}inline void Up(int g,int l){ v[g]=v[ls[g]]*pw[l]+v[rs[g]]; tot[g]=tot[ls[g]]+tot[rs[g]];}void Cover(int &g,int l,int r,int L,int R){ int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; tot[g]=tot[k]; v[g]=v[k]; if(l==L && r==R) return set0(g,L,R); int mid=L+R>>1; Push(g,L,R); if(r<=mid) Cover(ls[g],l,r,L,mid); else if(l>mid) Cover(rs[g],l,r,mid+1,R); else Cover(ls[g],l,mid,L,mid),Cover(rs[g],mid+1,r,mid+1,R); Up(g,R-mid);}void Modify(int &g,int x,int L,int R){ int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; tot[g]=tot[k]; v[g]=v[k]; if(L==R) return set1(g,L,R); int mid=L+R>>1; Push(g,L,R); if(x<=mid) Modify(ls[g],x,L,mid);else Modify(rs[g],x,mid+1,R); Up(g,R-mid);}inline int Same(int x,int y){ if(v[x]==v[y]) return n+1; int l=1,r=n; while(l<r){ int mid=l+r>>1; if(v[ls[x]]==v[ls[y]]) Push(rs[x],mid+1,r),Push(rs[y],mid+1,r),x=rs[x],y=rs[y],l=mid+1; else Push(ls[x],l,mid),Push(ls[y],l,mid),x=ls[x],y=ls[y],r=mid; } return l;}int main(){ rea(t); pw[0]=p[0]={1,1}; for(int i=1;i<=100000;i++) p[i]=p[i-1]+(pw[i]=pw[i-1]*base); while(t--){ rea(n); rea(q); S.clear(); memset(tag,-1,sizeof(tag)); g=0; ans=0; for(int i=1;i<=n;i++) rt[i]=0; cnt=0; for(int i=1;i<=q;i++){ if(i==4) int ssss=0; char c; while((c=nc())!='?' && c!='!'); if(c=='?') printf("%lld\n",max(ans,1LL)); else{ int x; rea(x); x=n-x; rt[g+1]=rt[g]; g++; int pos=Find(rt[g],1,x,1,n); if(~pos){ if(pos+1<=x) Cover(rt[g],pos+1,x,1,n); Modify(rt[g],pos,1,n); } else Cover(rt[g],1,x,1,n); Push(rt[g],1,n); if(S.find(u{rt[g]})!=S.end()){ continue; } set<u>::iterator IT=S.insert(u{rt[g]}).first; int cur=0; ans+=n+1; if(IT!=S.begin()) IT--,cur=Same(IT->x,rt[g]),IT++; IT++; if(IT!=S.end()) cur=max(cur,Same(IT->x,rt[g])); ans-=cur; } } } return 0;}
阅读全文
0 0
- [主席树维护HASH && SET维护DFS序] Codechef. Walks on the binary tree
- Codechef Aug2017 #Walks on the binary tree -- 主席树+Hash
- [主席树维护HASH] Codechef. Cloning
- BZOJ 3221 [Codechef FEB13] Obserbing the tree树上询问 树链剖分 主席树维护区间加等差数列
- 主席树维护dfs序——BZOJ3653/Luogu3899 谈笑风生
- [最短路 && 主席树维护HASH]Codeforces 464E. The Classic Problem
- 【BZOJ2588】Count on a tree,主席树维护链+ST表求LCA
- BZOJ 3991 set维护dfs序
- [最短路 && 主席树维护HASH] 51nod1863 Travel
- [贪心+DFS序列维护树上前缀和]2014 Multi-University Training Contest 5 - 1002 Paths on the tree
- [主席树 Hash] Codechef JUNE17 #CLONEME Cloning
- bzoj2588 Count on a tree dfs&主席树
- 用dfs序维护树结构
- 用dfs序维护树结构
- zoj 3686 A Simple Tree Problem (经典,利用dfs序维护树)
- cf-edu#6-E - New Year Tree -dfs序+线段树维护
- [BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- [省选前题目整理][BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- 符号管理
- 解决IE浏览器中解决IE浏览中AJAX只能运一次的IE缓存问题
- Unity入门操作_UGUI_Button理论_025
- python用open()函数打开.py等文档时出现编码错误解决办法
- Android项目汇总
- [主席树维护HASH && SET维护DFS序] Codechef. Walks on the binary tree
- Easyui Datagrid 根据字段动态合并行
- 用qt creator画实时图像
- js数组添加元素方式使用push
- strut2的进阶配置和属性参数设置获取问题
- py2exe的官方tutorial
- Socket,非阻塞,fcntl
- Log4j MDC使用案例
- Leetcode#53: Maximum Subarray