一些题目的代码被网站吞了……
Problem B. Red Black Tree
http://acm.zju.edu.cn/onlinejudge/searchProblem.do?contestId=1&titlefrom=0&authorfrom=0&sourcefrom=0&query=The+2018+ACM-ICPC+Asia+Qingdao+Regional+Contest%2C+Online
http://acm.zju.edu.cn/pcpst/index.html
http://acm.zju.edu.cn/contest-materials/qdol2018/qdol2018_problems.pdf
注意是找祖先(红色孩子节点无效)!
先按照花费对节点从大到小进行排序,依次增加一个点,这个点的花费采用从该点到所有新加入点的最近公共祖先的距离,直到遇到花费不可减少,则停止。
注意maxlen!
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn=1e5+10; 5 const double minv=1e-10; 6 const ll inf=1e18; 7 8 vector<pair<int,ll> >e[maxn]; 9 int r[maxn],dep[maxn<<1],p[maxn<<1],lef[maxn],er[21],point[maxn],ind,f[maxn<<1][21]; 10 ll cost[maxn],len[maxn]; 11 bool vis[maxn]; 12 13 void dfs(int d,ll c,ll l,int deep) 14 { 15 vis[d]=1; 16 if (r[d]==1) 17 c=0; 18 cost[d]=c; 19 len[d]=l; 20 dep[++ind]=deep; 21 p[ind]=d; 22 lef[d]=ind; 23 vector<pair<int,ll> >::iterator j; 24 for (j=e[d].begin();j!=e[d].end();j++) 25 if (!vis[j->first]) 26 { 27 dfs(j->first,c+j->second,l+j->second,deep+1); 28 dep[++ind]=deep; 29 p[ind]=d; 30 } 31 } 32 33 int cmp(int a,int b) 34 { 35 return cost[a]>cost[b]; 36 } 37 38 int main() 39 { 40 int t,n,m,q,u,v,d,deep,i,j,k; 41 ll w,result,maxlen; 42 for (i=0;i<=20;i++) 43 er[i]=1<<i; 44 scanf("%d",&t); 45 while (t--) 46 { 47 scanf("%d%d%d",&n,&m,&q); 48 for (i=1;i<=n;i++) 49 { 50 r[i]=0; 51 vis[i]=0; 52 e[i].clear(); 53 } 54 for (i=1;i<=m;i++) 55 scanf("%d",&d),r[d]=1; 56 for (i=1;i<n;i++) 57 { 58 scanf("%d%d%lld",&u,&v,&w); 59 e[u].push_back({v,w}); 60 e[v].push_back({u,w}); 61 } 62 ind=0; 63 dfs(1,0,0,0); 64 for (j=1;j<=ind;j++) 65 f[j][0]=j; 66 deep=(int)(log(ind)/log(2)+minv); 67 for (i=1;i<=deep;i++) 68 for (j=1,k=er[i-1]+1;j<=ind-er[i]+1;j++,k++) 69 f[j][i]=(dep[f[j][i-1]]<dep[f[k][i-1]])?f[j][i-1]:f[k][i-1]; 70 while (q--) 71 { 72 scanf("%d",&m); 73 for (i=1;i<=m;i++) 74 scanf("%d",&point[i]); 75 sort(point+1,point+m+1,cmp); 76 if (m==1) 77 result=0; 78 else 79 { 80 result=cost[point[2]]; 81 d=point[1]; 82 } 83 maxlen=len[point[1]]; 84 for (i=2;i<=m;i++) 85 { 86 u=lef[d]; 87 v=lef[point[i]]; 88 if (u>v) 89 swap(u,v); 90 deep=(int)(log(v-u+1)/log(2)+minv); 91 d=(dep[f[u][deep]]<dep[f[v-er[deep]+1][deep]])?f[u][deep]:f[v-er[deep]+1][deep]; 92 d=p[d]; 93 maxlen=max(maxlen,len[point[i]]); 94 w=maxlen-len[d]; 95 if (i==m || w>=cost[point[i+1]]) 96 { 97 result=min(result,w); 98 break; 99 } 100 result=min(result,cost[point[i+1]]); 101 } 102 printf("%lld\n",result); 103 } 104 } 105 return 0; 106 } 107 /* 108 10 109 10 2 100 110 7 10 111 1 2 3 112 1 3 4 113 1 4 1 114 2 5 1 115 3 6 2 116 5 7 3 117 3 8 2 118 4 9 3 119 9 10 10 120 5 1 2 3 4 5 121 122 */
另外:
对花费采用二分
参见 https://blog.csdn.net/qq_40993793/article/details/82762766,
每次询问O( klog(w*n) ),(其中排序那块我没看懂,这里的时间复杂度没有算排序)
sum(k)<=2e6,n<=1e5,w<=1e9,
因此log(w*n)=47,maxtime=9.4*10^7,存在超时的可能性(虽然假设的有点。。。)。不太推荐。。。
在zoj测试时,超时了
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn=1e5+10; 5 const double minv=1e-10; 6 const ll inf=1e18; 7 8 vector<pair<int,ll> >e[maxn]; 9 int red[maxn],dep[maxn<<1],p[maxn<<1],lef[maxn],er[21],point[maxn],ind,f[maxn<<1][21]; 10 ll cost[maxn],len[maxn]; 11 bool vis[maxn]; 12 13 void dfs(int d,ll c,ll l,int deep) 14 { 15 vis[d]=1; 16 if (red[d]==1) 17 c=0; 18 cost[d]=c; 19 len[d]=l; 20 dep[++ind]=deep; 21 p[ind]=d; 22 lef[d]=ind; 23 vector<pair<int,ll> >::iterator j; 24 for (j=e[d].begin();j!=e[d].end();j++) 25 if (!vis[j->first]) 26 { 27 dfs(j->first,c+j->second,l+j->second,deep+1); 28 dep[++ind]=deep; 29 p[ind]=d; 30 } 31 } 32 33 int cmp(int a,int b) 34 { 35 return cost[a]>cost[b]; 36 } 37 38 int main() 39 { 40 int t,n,m,q,u,v,g,d,deep,i,j,k,l; 41 ll w,result,r; 42 bool use; 43 for (i=0;i<=20;i++) 44 er[i]=1<<i; 45 scanf("%d",&t); 46 while (t--) 47 { 48 scanf("%d%d%d",&n,&m,&q); 49 for (i=1;i<=n;i++) 50 { 51 red[i]=0; 52 vis[i]=0; 53 e[i].clear(); 54 } 55 for (i=1;i<=m;i++) 56 scanf("%d",&d),red[d]=1; 57 for (i=1;i<n;i++) 58 { 59 scanf("%d%d%lld",&u,&v,&w); 60 e[u].push_back({v,w}); 61 e[v].push_back({u,w}); 62 } 63 ind=0; 64 dfs(1,0,0,0); 65 for (j=1;j<=ind;j++) 66 f[j][0]=j; 67 deep=(int)(log(ind)/log(2)+minv); 68 for (i=1;i<=deep;i++) 69 for (j=1,k=er[i-1]+1;j<=ind-er[i]+1;j++,k++) 70 f[j][i]=(dep[f[j][i-1]]<dep[f[k][i-1]])?f[j][i-1]:f[k][i-1]; 71 while (q--) 72 { 73 l=0; r=0; 74 scanf("%d",&g); 75 for (i=1;i<=g;i++) 76 { 77 scanf("%d",&point[i]); 78 r=max(r,cost[point[i]]); 79 } 80 while (l<=r) 81 { 82 m=(l+r)>>1; 83 use=0; 84 for (i=1;i<=g;i++) 85 if (cost[point[i]]>m) 86 { 87 if (!use) 88 { 89 use=1; 90 d=point[i]; 91 continue; 92 } 93 u=lef[d]; 94 v=lef[point[i]]; 95 if (u>v) 96 swap(u,v); 97 deep=(int)(log(v-u+1)/log(2)+minv); 98 d=(dep[f[u][deep]]<dep[f[v-er[deep]+1][deep]])?f[u][deep]:f[v-er[deep]+1][deep]; 99 d=p[d]; 100 if (len[point[1]]-len[d]>m) 101 break; 102 } 103 if (i==g+1) 104 r=m-1; 105 else 106 l=m+1; 107 } 108 printf("%lld\n",l); 109 } 110 } 111 return 0; 112 } 113 /* 114 10 115 10 2 100 116 7 10 117 1 2 3 118 1 3 4 119 1 4 1 120 2 5 1 121 3 6 2 122 5 7 3 123 3 8 2 124 4 9 3 125 9 10 10 126 5 1 2 3 4 5 127 128 */