2018 ACM 网络选拔赛 青岛赛区

时间:2021-02-03 21:10:38

 

一些题目的代码被网站吞了……

 

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 */