JZYZOJ1454 NOIP2015 D2T3_运输计划 二分 差分数组 lca tarjan 树链剖分
http://172.20.6.3/Problem_Show.asp?id=1454
从这道题我充分认识到我的脑子里好多水orz。
如果知道了这个要用二分和差分写,就没什么思考上的难点了(屁咧你写了一个下午)。
下面讲述一下我写这道题的辛酸历程:
我最开始写了个树链剖分+线段树+二分+差分数组,tle了一个点,这完全搞不懂啊,什么鬼啊,为什么啊,不然你告诉我怎么写啊。
然后我去找了a了此题的Lcentury大神,然后他告诉我:“这个题要用tarjan求lca啊,都什么年代了还用树链剖分,tanjan快啊,你这肯定要超时的。”然后我就信了Lcentury大神的邪学了一波tanjan。
我还很奇怪,tanjan怎么求两点之间距离啊???等到我辛辛苦苦读了一遍tanjan求两点距离的写法之后,狂喷凌霄血,原来只要找到lca一减就出来了,所以说树链剖分找lca是不会tle的,tle是因为我多加了一个sb线段树。
所以我两种都写了一遍[二哈],事实证明两种方案速度的确没有差很多。。。大数据一个是2609ms一个是2640ms。
下面展示我的两个代码(mdzz),就当mark模板了。
tanjan
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<iostream> 6 using namespace std; 7 #define lc x*2 8 #define rc x*2+1 9 const int maxn=300010; 10 int n,m; 11 struct nod{ 12 int next,y,v; 13 }e[maxn*2]; 14 int head[maxn]={},tot=0; 15 struct wtf{ 16 int x,y,fa,v; 17 }a[maxn]; 18 struct node{ 19 int y,id,next; 20 }d[maxn*2]; 21 int lin[maxn]={}; 22 int fa[maxn]={}; 23 int f[maxn]={}; 24 int cnt,ned; 25 int vis[maxn]={}; 26 int dis[maxn]={}; 27 inline void init(int x,int y,int v){ 28 e[++tot].y=y; 29 e[tot].v=v; 30 e[tot].next=head[x]; 31 head[x]=tot; 32 } 33 34 inline void insert(int x,int y,int id){ 35 d[++tot].y=y; 36 d[tot].id=id; 37 d[tot].next=lin[x]; 38 lin[x]=tot; 39 } 40 int read(){ 41 char ch=getchar();int x=0,f=1; 42 while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} 43 while(ch<='9'&&ch>='0'){x*=10;x+=ch-'0';ch=getchar();} 44 return x*f; 45 } 46 int find(int x){ 47 if(f[x]==-1) 48 return x; 49 return f[x]=find(f[x]); 50 } 51 void merge(int u,int v){ 52 int x=find(u); 53 int y=find(v); 54 if(x!=y) f[x]=y; 55 } 56 void tarj(int x){ 57 int y,v; 58 fa[x]=x; 59 vis[x]=1; 60 for(int i=head[x];i;i=e[i].next){ 61 y=e[i].y;v=e[i].v; 62 if(vis[y])continue; 63 dis[y]=dis[x]+v; 64 tarj(y); 65 merge(x,y); 66 fa[find(x)]=x; 67 } 68 for(int i=lin[x];i;i=d[i].next){ 69 y=d[i].y; 70 if(vis[y]) 71 a[d[i].id].fa=fa[find(y)]; 72 } 73 } 74 bool mmp(wtf aa,wtf bb){ 75 return aa.v>bb.v; 76 } 77 void dfs3(int x,int pa,int val){ 78 int y,v; 79 for(int i=head[x];i;i=e[i].next){ 80 y=e[i].y;v=e[i].v; 81 if(y==pa)continue; 82 dfs3(y,x,v); 83 vis[x]+=vis[y]; 84 } 85 // cout<<ned<<vis[x]<<val<<x<<endl; 86 if(vis[x]==ned)cnt=max(cnt,val); 87 } 88 inline bool check(int x){ 89 cnt=0; 90 memset(vis,0,sizeof(vis)); 91 for(int i=1;i<=m;i++){ 92 if(a[i].v>x){ 93 vis[a[i].x]++; 94 vis[a[i].y]++; 95 vis[a[i].fa]-=2; 96 } 97 else{ 98 ned=i-1; 99 break; 100 } 101 if(i==m)ned=m; 102 } 103 dfs3(1,1,0); 104 if(a[1].v-cnt<=x)return 1; 105 else return 0; 106 } 107 inline int doit(){ 108 int l=0,r=a[1].v; 109 while(l<r){ 110 int mid=(l+r)/2; 111 if(check(mid))r=mid; 112 else l=mid+1; 113 } 114 return l; 115 } 116 int main(){ 117 //freopen("wtf.in","r",stdin); 118 int size=128<<20; 119 char *p=(char*)malloc(size)+size; 120 __asm__("movl %0,%%esp\n"::"r"(p)); 121 n=read();m=read(); 122 int x,y,v; 123 for(int i=1;i<n;i++){ 124 x=read();y=read();v=read(); 125 init(x,y,v);init(y,x,v); 126 }tot=0; 127 for(int i=1;i<=m;i++){ 128 a[i].x=read();a[i].y=read(); 129 insert(a[i].x,a[i].y,i); 130 insert(a[i].y,a[i].x,i); 131 }memset(f,-1,sizeof(f)); 132 tarj(1); 133 for(int i=1;i<=m;i++){ 134 a[i].v=dis[a[i].x]+dis[a[i].y]-dis[a[i].fa]*2; 135 } 136 sort(a+1,a+1+m,mmp); 137 printf("%d\n",doit()); 138 return 0; 139 }
树链剖分
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<iostream> 6 using namespace std; 7 #define lc x*2 8 #define rc x*2+1 9 const int maxn=300010; 10 int n,m; 11 struct nod{ 12 int next,y,v; 13 }e[maxn*2]; 14 int head[maxn]={},tot=0; 15 int dep[maxn]={},fa[maxn]={},kid[maxn]={}; 16 int top[maxn]={}; 17 int dis[maxn]={}; 18 inline void init(int x,int y,int v){ 19 e[++tot].y=y; 20 e[tot].v=v; 21 e[tot].next=head[x]; 22 head[x]=tot; 23 } 24 int dfs(int x,int pa){ 25 int y,val,v,tsn=0,hug=0; 26 dep[x]=dep[pa]+1; 27 fa[x]=pa; 28 for(int i=head[x];i;i=e[i].next){ 29 y=e[i].y;v=e[i].v; 30 if(y==pa)continue; 31 dis[y]=dis[x]+v; 32 val=dfs(y,x); 33 if(val>hug)hug=val,kid[x]=y; 34 tsn+=val; 35 } 36 tsn+=1; 37 return tsn; 38 } 39 void dfs1(int x,int pa){ 40 int y,v; 41 top[x]=pa; 42 if(kid[x])dfs1(kid[x],pa); 43 for(int i=head[x];i;i=e[i].next){ 44 y=e[i].y;v=e[i].v; 45 if(y==fa[x]||y==kid[x])continue; 46 dfs1(y,y); 47 } 48 } 49 int getit(int x,int y){ 50 int xx=top[x],yy=top[y]; 51 while(xx!=yy){ 52 if(dep[xx]<dep[yy]){ 53 swap(xx,yy); 54 swap(x,y); 55 } 56 x=fa[xx];xx=top[x]; 57 } 58 if(dep[x]>dep[y])return y; 59 return x; 60 } 61 int read(){ 62 char ch=getchar();int x=0,f=1; 63 while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} 64 while(ch<='9'&&ch>='0'){x*=10;x+=ch-'0';ch=getchar();} 65 return x*f; 66 } 67 struct wtf{ 68 int x,y,fa,v; 69 }a[maxn]; 70 bool mmp(wtf aa,wtf bb){ 71 return aa.v>bb.v; 72 } 73 int cnt,ned; 74 int vis[maxn]={}; 75 void dfs3(int x,int val){ 76 int y,v; 77 for(int i=head[x];i;i=e[i].next){ 78 y=e[i].y;v=e[i].v; 79 if(y==fa[x])continue; 80 dfs3(y,v); 81 vis[x]+=vis[y]; 82 } 83 if(vis[x]==ned)cnt=max(cnt,val); 84 } 85 inline bool check(int x){ 86 cnt=0; 87 memset(vis,0,sizeof(vis)); 88 for(int i=1;i<=m;i++){ 89 if(a[i].v>x){ 90 vis[a[i].x]++; 91 vis[a[i].y]++; 92 vis[a[i].fa]-=2; 93 } 94 else{ 95 ned=i-1; 96 break; 97 } 98 if(i==m)ned=m; 99 } 100 dfs3(1,0); 101 if(a[1].v-cnt<=x)return 1; 102 else return 0; 103 } 104 inline int doit(){ 105 int l=0,r=a[1].v; 106 while(l<r){ 107 int mid=(l+r)/2; 108 if(check(mid))r=mid; 109 else l=mid+1; 110 } 111 return l; 112 } 113 int main(){ 114 //freopen("wtf.in","r",stdin); 115 int size=128<<20; 116 char *p=(char*)malloc(size)+size; 117 __asm__("movl %0,%%esp\n"::"r"(p)); 118 n=read();m=read(); 119 int x,y,v; 120 for(int i=1;i<n;i++){ 121 x=read();y=read();v=read(); 122 init(x,y,v);init(y,x,v); 123 }dfs(1,1); 124 dfs1(1,1); 125 for(int i=1;i<=m;i++){ 126 a[i].x=read();a[i].y=read(); 127 a[i].fa=getit(a[i].x,a[i].y); 128 a[i].v=dis[a[i].x]+dis[a[i].y]-2*dis[a[i].fa]; 129 }sort(a+1,a+1+m,mmp); 130 printf("%d\n",doit()); 131 return 0; 132 }