Luogu2542 AHOI2005 航线规划 树链剖分线段树
Posted itst
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu2542 AHOI2005 航线规划 树链剖分线段树相关的知识,希望对你有一定的参考价值。
看到删边不用想就是反着加边
先把删完边之后的图拆一个生成树出来,然后考虑非树边的影响。实际上非树边就是让树上的一条路径的权值从$1$变为了$0$,而每一个询问就是一条路径上的权值之和。使用树链剖分+线段树维护权值即可。
1 #include<bits/stdc++.h> 2 #define lch (now << 1) 3 #define rch (now << 1 | 1) 4 #define mid ((l + r) >> 1) 5 //This code is written by Itst 6 using namespace std; 7 8 inline int read(){ 9 int a = 0; 10 bool f = 0; 11 char c = getchar(); 12 while(c != EOF && !isdigit(c)){ 13 if(c == ‘-‘) 14 f = 1; 15 c = getchar(); 16 } 17 while(c != EOF && isdigit(c)){ 18 a = (a << 3) + (a << 1) + (c ^ ‘0‘); 19 c = getchar(); 20 } 21 return f ? -a : a; 22 } 23 24 const int MAXN = 30010; 25 struct Edge{ 26 int end , upEd; 27 }Ed[MAXN << 3]; 28 struct query{ 29 int type , s , t; 30 }now[MAXN << 1]; 31 int head[MAXN] , sum[MAXN << 2] , mark[MAXN << 2] , ans[MAXN << 1] , N , M , cntEd , cntQ , cntAns; 32 int top[MAXN] , dep[MAXN] , fa[MAXN] , son[MAXN] , ind[MAXN] , size[MAXN] , ts; 33 vector < int > bef[MAXN] , del[MAXN]; 34 bool vis[MAXN]; 35 36 inline void addEd(int a , int b){ 37 Ed[++cntEd].end = b; 38 Ed[cntEd].upEd = head[a]; 39 head[a] = cntEd; 40 } 41 42 void dfs1(int x , int f){ 43 size[x] = 1; 44 fa[x] = f; 45 dep[x] = dep[f] + 1; 46 for(int i = head[x] ; i ; i = Ed[i].upEd) 47 if(!dep[Ed[i].end]){ 48 dfs1(Ed[i].end , x); 49 size[x] += size[Ed[i].end]; 50 if(size[Ed[i].end] > size[son[x]]) 51 son[x] = Ed[i].end; 52 } 53 } 54 55 void dfs2(int x , int t){ 56 top[x] = t; 57 ind[x] = ++ts; 58 if(!son[x]) 59 return; 60 dfs2(son[x] , t); 61 for(int i = head[x] ; i ; i = Ed[i].upEd) 62 if(fa[Ed[i].end] == x && Ed[i].end != son[x]) 63 dfs2(Ed[i].end , Ed[i].end); 64 } 65 66 inline void pushup(int now){ 67 sum[now] = sum[lch] + sum[rch]; 68 } 69 70 inline void pushdown(int now , int l , int r){ 71 if(mark[now] != -1){ 72 mark[lch] = mark[now]; 73 mark[rch] = mark[now]; 74 sum[lch] = mark[now] * (mid - l + 1); 75 sum[rch] = mark[now] * (r - mid); 76 mark[now] = -1; 77 } 78 } 79 80 int query(int now , int l , int r , int L , int R){ 81 if(l >= L && r <= R) 82 return sum[now]; 83 pushdown(now , l , r); 84 int sum = 0; 85 if(mid >= L) 86 sum = query(lch , l , mid , L , R); 87 if(mid < R) 88 sum += query(rch , mid + 1 , r , L , R); 89 return sum; 90 } 91 92 void modify(int now , int l , int r , int L , int R , int num){ 93 if(l >= L && r <= R){ 94 mark[now] = num; 95 sum[now] = num * (r - l + 1); 96 return; 97 } 98 pushdown(now , l , r); 99 if(mid >= L) 100 modify(lch , l , mid , L , R , num); 101 if(mid < R) 102 modify(rch , mid + 1 , r , L , R , num); 103 pushup(now); 104 } 105 106 inline void work(int x , int y){ 107 int tx = top[x] , ty = top[y]; 108 while(tx != ty){ 109 if(dep[tx] < dep[ty]){ 110 swap(tx , ty); 111 swap(x , y); 112 } 113 modify(1 , 1 , N , ind[tx] , ind[x] , 0); 114 x = fa[x]; 115 tx = top[x]; 116 } 117 if(dep[x] > dep[y]) 118 swap(x , y); 119 if(dep[x] != dep[y]) 120 modify(1 , 1 , N , ind[x] + 1 , ind[y] , 0); 121 } 122 123 inline int query(int x , int y){ 124 int sum = 0 , tx = top[x] , ty = top[y]; 125 while(tx != ty){ 126 if(dep[tx] < dep[ty]){ 127 swap(tx , ty); 128 swap(x , y); 129 } 130 sum += query(1 , 1 , N , ind[tx] , ind[x]); 131 x = fa[tx]; 132 tx = top[x]; 133 } 134 if(dep[x] > dep[y]) 135 swap(x , y); 136 if(dep[x] != dep[y]) 137 sum += query(1 , 1 , N , ind[x] + 1 , ind[y]); 138 return sum; 139 } 140 141 void dfs3(int now){ 142 vis[now] = 1; 143 for(int i = head[now] ; i ; i = Ed[i].upEd) 144 if(fa[Ed[i].end] == now && !vis[Ed[i].end]) 145 dfs3(Ed[i].end); 146 else 147 if(dep[Ed[i].end] >= dep[now]) 148 work(now , Ed[i].end); 149 } 150 151 int main(){ 152 #ifndef ONLINE_JUDGE 153 freopen("2542.in" , "r" , stdin); 154 freopen("2542.out" , "w" , stdout); 155 #endif 156 memset(mark , -1 , sizeof(mark)); 157 N = read(); 158 M = read(); 159 modify(1 , 1 , N , 1 , N , 1); 160 for(int i = 1 ; i <= M ; ++i){ 161 int a = read() , b = read(); 162 bef[a].push_back(b); 163 bef[b].push_back(a); 164 } 165 for(int i = 1 ; i <= N ; ++i) 166 sort(bef[i].begin() , bef[i].end()); 167 int c = read(); 168 while(c + 1){ 169 now[++cntQ].type = c; 170 now[cntQ].s = read(); 171 now[cntQ].t = read(); 172 if(!c){ 173 del[now[cntQ].s].push_back(now[cntQ].t); 174 del[now[cntQ].t].push_back(now[cntQ].s); 175 } 176 c = read(); 177 } 178 for(int i = 1 ; i <= N ; ++i){ 179 sort(del[i].begin() , del[i].end()); 180 int p = 0 , sizeb = bef[i].size() , sized = del[i].size(); 181 for(int j = 0 ; j < sizeb ; ++j) 182 if(p < sized && bef[i][j] == del[i][p]) 183 ++p; 184 else 185 addEd(i , bef[i][j]); 186 } 187 dfs1(1 , 0); 188 dfs2(1 , 1); 189 dfs3(1); 190 for(int i = cntQ ; i ; --i) 191 if(now[i].type) 192 ans[++cntAns] = query(now[i].s , now[i].t); 193 else 194 work(now[i].s , now[i].t); 195 while(cntAns) 196 printf("%d " , ans[cntAns--]); 197 return 0; 198 }
以上是关于Luogu2542 AHOI2005 航线规划 树链剖分线段树的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1969[Ahoi2005]LANE 航线规划 离线+树链剖分+线段树
bzoj1959[Ahoi2005]LANE 航线规划 离线处理+树链剖分+线段树