csu1798: 小Z的城市 线段树+ST表
来源:互联网 发布:罗元裳是骗局吗 知乎 编辑:程序博客网 时间:2024/06/05 15:48
题目链接点这里
终于把去年省热身赛的这题补了,,,好久没写这么复杂的题了,,写了2个小时,,调了一个小时bug。。总共花3小时,,,还是太菜了。。
,,大概,用ST表求任意2点间的距离
线段树查询任意一个区间的最大路径。。。。。
#include<algorithm>#include<iostream>#include<cstring>#include<queue>#include<cmath>#include<cstdio>using namespace std;#define mem(x,y) memset(x,y,sizeof(x))#define FIN freopen("input.txt","r",stdin)#define fuck(x) cout<<x<<endlconst int MX=111111;#define INF 0x3f3f3f3f#define lson l,m,rt<<1typedef long long LL;typedef pair<int,int> PII;#define rson m+1,r,rt<<1|1#define lson l,m,rt<<1int n,m;int head[MX],cnt;struct Edge{ int nxt,to,dis;} E[2*MX];void edge_init(){ mem(head,-1); cnt=0;}void edge_add(int u,int v,int dis){ E[cnt].nxt=head[u]; E[cnt].to=v; E[cnt].dis=dis; head[u]=cnt++;}int w[20][2*MX],n_cnt;//ST表int dis[MX];//每个点到根节点的距离int p[MX];//每个节点出现的最先编号int dep[MX];//每个节点的深度void dfs(int u,int d,int fa,int dist){ p[u]=n_cnt; w[0][n_cnt++]=u; dep[u]=d; dis[u]=dist; for(int i=head[u]; ~i; i=E[i].nxt) { int v=E[i].to; if(v==fa)continue; dfs(v,d+1,u,dist+E[i].dis); w[0][n_cnt++]=u; }}void ST_init(){ for(int i=1; (1<<i)<=n_cnt; i++) { for(int j=0; j+(1<<i)<=n_cnt; j++) { if(dep[w[i-1][j]]<=dep[w[i-1][j+(1<<(i-1))]]) w[i][j]=w[i-1][j]; else w[i][j]=w[i-1][j+(1<<(i-1))]; } }}int ST_query(int u,int v){ int l=p[u],r=p[v]; if(l>r) swap(l,r); int len=r-l+1,i; for(i=0; (1<<i)<=len; i++); i--; int fa; if(dep[w[i][l]]>dep[w[i][r-(1<<i)+1]]) fa=w[i][r-(1<<i)+1]; else fa=w[i][l]; return dis[u]+dis[v]-2*dis[fa];}//线段树int sum[MX<<2][2];PII bin(PII a,PII b){ // cout<<a.first<<" "<<a.second<<" "<<b.first<<" "<<b.second<<endl; PII c; int x1,x2,x3,x4,x5,x6; if(a.second!=-1&&b.second!=-1) x4=ST_query(a.second,b.second); else x4=-INF; x3=ST_query(a.first,b.first); if(a.second==-1)x1=x5=-INF; else { x1=ST_query(a.first,a.second); x5=ST_query(a.second,b.first); } if(b.second==-1)x2=x6=-INF; else { x2=ST_query(b.first,b.second); x6=ST_query(a.first,b.second); } int mx=max(x1,x2); mx=max(mx,x3); mx=max(mx,x4); mx=max(mx,x5); mx=max(mx,x6); if(mx==x1) c.first=a.first,c.second=a.second; else if(mx==x2) c.first=b.first,c.second=b.second; else if(mx==x3) c.first=a.first,c.second=b.first; else if(mx==x4) c.first=a.second,c.second=b.second; else if(mx==x5) c.first=a.second,c.second=b.first; else if(mx==x6) c.first=a.first,c.second=b.second; return c;}void build(int l,int r,int rt){ if(l==r) { sum[rt][0]=l; sum[rt][1]=-1; return ; } int m=(l+r)>>1; build(lson); build(rson); PII a=bin(PII(sum[rt<<1][0],sum[rt<<1][1]),PII(sum[rt<<1|1][0],sum[rt<<1|1][1])); sum[rt][0]=a.first; sum[rt][1]=a.second;}PII query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) { return PII(sum[rt][0],sum[rt][1]); } int m=(l+r)>>1; PII a,b; if(m>=L) a=query(L,R,lson); if(m+1<=R) b=query(L,R,rson); if(!a.first)return b; if(!b.first)return a; return bin(a,b);}int main(){ FIN; while(cin>>n>>m) { edge_init(); for(int i=1; i<n; i++) { int u,v,dis; scanf("%d%d%d",&u,&v,&dis); edge_add(u,v,dis); edge_add(v,u,dis); } n_cnt=0; dfs(1,1,-1,0); //fuck(n_cnt); //for(int i=0; i<n_cnt; i++)printf("%d ",w[0][i]); ST_init(); build(1,n,1); for(int i=1; i<=m; i++) { int u,v; scanf("%d%d",&u,&v); PII a=query(u,v,1,n,1); if(u>v)swap(u,v); // cout<<a.first<<" "<<a.second<<endl; printf("%d\n",ST_query(a.first,a.second)); } } return 0;}
0 0
- csu1798: 小Z的城市 线段树+ST表
- csu1798 小Z的城市
- POJ_3368_Frequent values_线段树/ST稀疏表
- POJ3264 Balanced Lineup 线段树|ST表
- nyoj1068 ST 线段树
- RMQ问题 (st+线段树)
- POJ 3264 线段树 ST
- RMQ的两种实现ST算法,和线段树
- [Noi2010] D1T2 超级钢琴 (ST表 线段树 主席树)
- Balanced Lineup-POJ - 3264-RMQ线段树/st表
- Codevs 4373 窗口(线段树 单调队列 st表)
- HDU 5875 Function 线段树 || (ST表 + 二分)
- HDU 5875 Function (ST表+二分 or 线段树)
- 维护区间gcd(线段树 || ST表+二分)
- [bzoj4722]由乃 线段树 搜索 st表
- 小城市的信息化
- 小Z的袜子
- 小z的袜子
- 异步线程之AsyncTask
- innodb存储引擎笔记(上)
- 前端构建工具gulpjs的使用介绍及技巧
- STL中的nth_element()方法的使用
- 蓝桥杯-算法提高-队列操作
- csu1798: 小Z的城市 线段树+ST表
- android之ListView重写item里面的事件
- shell中的变量赋值
- android网络配置
- 改不少次,全是小错误
- poj3974:Palindrome(manacher模板)
- make modules_install指定ko安装路径
- C#如何查找指定目录下文件示例
- cs231n学习心得