BZOJ 3631 [JLOI2014]松鼠的新家==树剖
2016-07-19 19:26
381 查看
题目传送门:23333
十分考验树剖的本事
在网上看到几个大神写树剖T掉了233333
主要是树剖,剖完后把一条路上的点不停地打永久标记,不用向下推,查询时直接把flag加起来就好了。
另外除了第一个点外其余点都要减一,中间的点进入会拿一颗糖,出时也会计算一个,所以要减去。
最后一个房间的糖题目说了不用,所以也要减。
(虽说被这个坑了好久QAQ)
十分考验树剖的本事
在网上看到几个大神写树剖T掉了233333
主要是树剖,剖完后把一条路上的点不停地打永久标记,不用向下推,查询时直接把flag加起来就好了。
另外除了第一个点外其余点都要减一,中间的点进入会拿一颗糖,出时也会计算一个,所以要减去。
最后一个房间的糖题目说了不用,所以也要减。
(虽说被这个坑了好久QAQ)
#include <cstdio> #include <algorithm> #include <cstring> #include <iostream> #define rep(j,k,l) for (int j=k;j<=l;j++) #define N 300005 using namespace std; struct _233{ int l,r,flag; } tr[N*4]; int n,cnt,a ,ne[N*2],to[N*2],st ; int as ,size ,son ,deep ,fa ,top ,dfn ,id ; void add(int k,int l,int p){ to[p]=l; ne[p]=st[k]; st[k]=p; } void dfs1(int rt,int dad){ size[rt]=1; fa[rt]=dad; deep[rt]=deep[dad]+1; son[rt]=0;int _=0; for (int i=st[rt];i!=0;i=ne[i]) if (to[i]!=dad){ dfs1(to[i],rt); size[rt]+=size[to[i]]; if (size[to[i]]>_){ _=size[to[i]]; son[rt]=to[i]; } } } void dfs2(int rt,bool qaz){ if (qaz) top[rt]=top[fa[rt]]; else top[rt]=rt; dfn[++cnt]=rt; id[rt]=cnt; if (son[rt]!=0) dfs2(son[rt],1); for (int i=st[rt];i!=0;i=ne[i]) if (to[i]!=fa[rt]&&to[i]!=son[rt]) dfs2(to[i],0); } void stree(int k,int l,int r){ if (l==r) return; tr[k].l=++cnt; tr[k].r=++cnt; stree(tr[k].l,l,(l+r)/2); stree(tr[k].r,(l+r)/2+1,r); } void change(int k,int l,int r,int o,int p){ if (o>r||p<l) return; if (o<=l&&r<=p){ tr[k].flag+=1; return; } change(tr[k].l,l,(l+r)/2,o,p); change(tr[k].r,(l+r)/2+1,r,o,p); return; } void work(int x,int y){ for (;top[x]!=top[y];x=fa[top[x]]){ if (deep[top[x]]<deep[top[y]]) swap(x,y); change(1,1,n,id[top[x]],id[x]); //printf("%d %d\n",top[x],x); } change(1,1,n,min(id[x],id[y]),max(id[x],id[y])); //printf("%d %d\n",min(id[x],id[y]),max(id[x],id[y])); //printf("\n"); } void print(int k,int l,int r,int f){ if (l==r){ if (dfn[l]==a[1]) f++; as[dfn[l]]=f+tr[k].flag; return; } print(tr[k].l,l,(l+r)/2,f+tr[k].flag); print(tr[k].r,(l+r)/2+1,r,f+tr[k].flag); } void tiaoshi(int k,int l,int r){ printf("%d %d %d\n",l,r,tr[k].flag); if (l==r) return; tiaoshi(tr[k].l,l,(l+r)/2); tiaoshi(tr[k].r,(l+r)/2+1,r); } int main(){ scanf("%d",&n); rep(i,1,n) scanf("%d",&a[i]); rep(i,1,n-1){ int k,l; scanf("%d%d",&k,&l); add(k,l,2*i-1); add(l,k,2*i); } dfs1(1,0); dfs2(1,0); cnt=1; stree(1,1,n); //for(int i=1;i<=5;i++) printf("%d\n",top[i]); rep(i,2,n) work(a[i],a[i-1]);//tiaoshi(1,1,n),printf("\n"); print(1,1,n,0); rep(i,1,n) printf("%d\n",as[i]-1); system("pause"); }
相关文章推荐
- 自定义圆形QLabel控件
- MySQL之聚合函数查询
- Java进阶(三十五)java int与integer的区别
- python3的函数调用
- Java进阶(三十五)java int与integer的区别
- Kafka入门经典教程
- Python——5函数
- Java编程基础
- Oracle查询问题引发临时表使用
- Android收集应用崩溃信息
- [HDU 5726] GCD (倍增法+二分)
- UVA 10474-Where is the Marble?
- AFNetworking2安全的使用自签证书访问HTTPS
- hdu 5464(简单dp)
- hdu 5733 tetrahedron(2016 Multi-University Training Contest 1计算几何)
- 如何在ubuntu下安装vmware-tools
- 【HDU 1175】连连看(DFS)
- UVA 327 Evaluating Simple C Expressions
- 纯CSS视差滚动
- HDOJ--2187 老人是真饿了(sort+结构体+贪心)