T1:给定一棵以1号点为根的树,每条边上有字母。定义一个节点的串为该节点走到根节点的路径字符。给定若干个询问,每次询问给定一个点集,询问这若干个点两两之间的lcp总和。
真心对字符串的题不感冒啊。我们考虑构建广义自动机。为什么呢,我们先考虑一个弱智版题目,如果给你一个trie,然后做同样的事情,那么我们完全可以建一个虚树,然后对于每一个节点贡献就是一个关于子树大小的很好求的东西。构建广义后缀自动机之后的parent树其实就是这么一个压缩了一些的trie。然后我们就可以做啦。
由于虚树没写过,SAM有一段时间没写过了,感觉很难写的样子。所以暂(yong)时(yuan)不写了。
T2:给定一棵完全二叉树,每个节点可以容纳xi个东西,给定一个大小为n的点集(里面的点可以重复),分别求对于每一个k(1<=k<=n),这n个点前k个点全部被容纳的代价。容纳代价为这个节点原先的位置到它被容纳节点的距离。
首先很容易得到一个最小费用流算法。但是这还不够,因为我们没有用到一个很重要的,一看就知道最终复杂度是nlogn的条件:完全二叉树。那么肯定是树高大有文章。我们考虑每次费用流,如果我们把源点和汇点去掉的话,然后每一条边是树边的话,每次费用流复杂度就是n的。这还不够,我们发现树高很小,那么我们用树形dp来维护这个费用流的边,每次跑完之后logn更新一下,总复杂度就是nlogn了。
每个节点我们维护一个pair,表示它子树里离它最近的点的距离是多少,这个点是什么。还维护了一个r数组。这特别关键,我们用它来记录这个点的反向边。我们定义向上爬为正方向,向下那就是反向边了。每次爬树高dp的时候我们要考虑反向边的存在,加加减减就好了
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define N 100005 5 #define INF 1e9 6 inline LL read(){ 7 LL x=0,f=1; char a=getchar(); 8 while(a<'0' || a>'9') {if(a=='-') f=-1; a=getchar();} 9 while(a>='0' && a<='9') x=x*10+a-'0',a=getchar(); 10 return x*f; 11 } 12 int n,m,c[N],p[N],r[N]; 13 LL ans; 14 struct dp{ 15 int dep,num; 16 bool operator < (const dp& w)const{ 17 return dep<w.dep; 18 } 19 }f[N]; 20 dp operator + (const dp& a,const int& b){ 21 return (dp){a.dep+b,a.num}; 22 } 23 inline void update(int x){ 24 if(c[x]) f[x]=(dp){0,x}; else f[x]=(dp){INF,0}; 25 if((x<<1)<=n) f[x]=min(f[x],f[x<<1]+(r[x<<1]>=0?1:-1)); 26 if((x<<1|1)<=n) f[x]=min(f[x],f[x<<1|1]+(r[x<<1|1]>=0?1:-1)); 27 } 28 int main(){ 29 n=read(); m=read(); 30 for(int i=1;i<=n;i++) c[i]=read(); 31 for(int i=1;i<=m;i++) p[i]=read(); 32 for(int i=n;i;i--) update(i); 33 for(int x,y,i=1;i<=m;i++){ 34 x=p[i]; 35 dp mn=(dp){INF,0}; int t=0; 36 while(x) mn=min(mn,f[x]+(t)),t+=(r[x]<=0?1:-1),x>>=1; 37 x=p[i]; y=mn.num; c[y]--; 38 while(x!=y){ 39 if(x>y) r[x]--,update(x),x>>=1; 40 else r[y]++,update(y),y>>=1; 41 } 42 while(x) update(x),x>>=1; 43 ans+=mn.dep; 44 printf("%lld ",ans); 45 } 46 return 0; 47 }
T3:KD_tree板题,第一次写KD_tree
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define N 400005 5 #define INF 1e9 6 inline LL read(){ 7 LL x=0,f=1; char a=getchar(); 8 while(a<'0' || a>'9') {if(a=='-') f=-1; a=getchar();} 9 while(a>='0' && a<='9') x=x*10+a-'0',a=getchar(); 10 return x*f; 11 } 12 int n,cnt,num[N],pos[N],root,ans,tmp; 13 struct point{ 14 int x,y,a,b,id; 15 inline void get(){ 16 x=read(); y=read(); a=read(); b=read(); 17 } 18 bool operator < (const point& w)const{ 19 if(x==w.x) return y<w.y; 20 return x<w.x; 21 } 22 }p[N]; 23 inline bool cmp(int x,int y){ 24 return p[x]<p[y]; 25 } 26 struct KD_tree{ 27 int xl,xr,yb,yt,l,r; 28 int son[2],mx,kind; 29 inline void init(){ 30 xl=INF; xr=0; yb=INF; yt=0; 31 } 32 }a[N]; 33 inline bool cmpx(const point& a,const point& b){return a.x<b.x;} 34 inline bool cmpy(const point& a,const point& b){return a.y<b.y;} 35 inline void update(int k){a[k].mx=max(a[a[k].son[0]].mx,a[a[k].son[1]].mx);} 36 void build(int& k,int l,int r){ 37 k=++cnt; a[k].l=l; a[k].r=r; 38 int F,mid=(l+r)>>1; 39 a[k].init(); 40 for(int i=l;i<=r;i++){ 41 a[k].xl=min(a[k].xl,p[i].x); 42 a[k].xr=max(a[k].xr,p[i].x); 43 a[k].yb=min(a[k].yb,p[i].y); 44 a[k].yt=max(a[k].yt,p[i].y); 45 } 46 if(l==r) return; 47 a[k].kind=F=a[k].xr-a[k].xl>a[k].yt-a[k].yb?0:1; 48 if(!F) nth_element(p+l,p+mid,p+r+1,cmpx); 49 else nth_element(p+l,p+mid,p+r+1,cmpy); 50 build(a[k].son[0],l,mid); build(a[k].son[1],mid+1,r); 51 update(k); 52 } 53 void modify(int k,int x,int val){ 54 if(a[k].l==a[k].r) a[k].mx=val; 55 else{ 56 int F=(x<=(a[k].l+a[k].r)/2?0:1); 57 modify(a[k].son[F],x,val); 58 update(k); 59 } 60 } 61 int query(int k,int xl,int xr,int yb,int yt){ 62 if(a[k].yt<yb || a[k].yb>yt || a[k].xl>xr || a[k].xr<xl) return 0; 63 if(a[k].yt<=yt && a[k].yb>=yb && a[k].xl>=xl && a[k].xr<=xr) return a[k].mx; 64 int ret=0,F=(a[a[k].son[0]].mx>a[a[k].son[1]].mx?0:1); //优化 65 ret=query(a[k].son[F],xl,xr,yb,yt); 66 if(ret<a[a[k].son[F^1]].mx) ret=max(ret,query(a[k].son[F^1],xl,xr,yb,yt)); 67 return ret; 68 } 69 int main(){ 70 n=read(); 71 for(int i=1;i<=n;i++) num[i]=i,p[i].id=i,p[i].get(); 72 sort(num+1,num+1+n,cmp); 73 build(root,1,n); 74 for(int i=1;i<=n;i++) pos[p[i].id]=i; 75 for(int x,i=n;i;i--){ 76 x=pos[num[i]]; 77 tmp=query(root,p[x].x,p[x].a,p[x].y,p[x].b)+1; 78 ans=max(ans,tmp); 79 modify(root,x,tmp); 80 } 81 printf("%d\n",ans); 82 return 0; 83 }