zoukankan      html  css  js  c++  java
  • bzoj3784 树上的路径

    Description
    给定一个N个结点的树,结点用正整数1..N编号。每条边有一个正整数权值。用d(a,b)表示从结点a到结点b路边上经过边的权值。其中要求a<b.将这n*(n-1)/2个距离从大到小排序,输出前M个距离值。

    Input
    第一行两个正整数N,M
    下面N-1行,每行三个正整数a,b,c(a,b<=N,C<=10000)。表示结点a到结点b有一条权值为c的边。

    Output
    共M行,如题所述.

    Sample Input
    5 10
    1 2 1
    1 3 2
    2 4 3
    2 5 4

    Sample Output
    7
    7
    6
    5
    4
    4
    3
    3
    2
    1

    Sample Input
    4 6
    1 2 1
    1 3 2
    1 4 4

    Sample Output
    6
    5
    4
    3
    2
    1

    HINT
    N<=50000,M<=Min(300000,n*(n-1)/2)

    以下仅为解题记录(并非题解)

    首先点分治,对每个节点搞出它所管辖的连通块中各个点到它的距离(包括自身,距离就是0),放进一个vector。

    处理出每个点的vector后,分别对各个vector中的元素排序,然后用堆取前k大答案。

    然后就会发现,这样是有问题的,还不是一点点的问题,这样不能把同子树的分离开。。。。

    (我到底在想些什么才能连这一点都想不到的啊。。。。。)

    然而这个好办,只要在搞出每个点管辖区域的各个点到它的距离时,顺便多记录一个值——每一个距离对应的子树编号。

    然后我就非常naive地在最后输出答案的时候,如果堆中弹出的是不合法的(有相同子树编号的),就跳过

      1 #pragma GCC optimize("Ofast")
      2 #pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
      3 #pragma GCC diagnostic error "-fwhole-program"
      4 #pragma GCC diagnostic error "-fcse-skip-blocks"
      5 #pragma GCC diagnostic error "-funsafe-loop-optimizations"
      6 #pragma GCC diagnostic error "-std=c++14"
      7 #include<cstdio>
      8 #include<algorithm>
      9 #include<vector>
     10 #include<queue>
     11 #include<map>
     12 using namespace std;
     13 typedef long long LL;
     14 typedef pair<LL,int> P;
     15 struct E
     16 {
     17     int to,nxt,d;
     18 }e[400100];
     19 int f1[200100],n,k,ne;
     20 vector<P> xx[200100];
     21 //表示i点管辖的连通块内各点到自身的距离(second表示子树编号)
     22 vector<int> nowed[200100];
     23 //表示xx[i]中取,左端点取j时,当前取右端点的位置
     24 int fx[200100],root,sz[200100],sum,nowsec;
     25 LL dep[200010];
     26 bool vis[200100];
     27 struct Info
     28 {
     29     LL ans;int nn,l;
     30     Info(LL a=0,int b=0,int c=0)
     31         :ans(a),nn(b),l(c)
     32     {}
     33     friend bool operator<(const Info &a,const Info &b)
     34     {
     35         return a.ans<b.ans;
     36     }
     37 };
     38 priority_queue<Info> q;
     39 void getroot(int u,int fa)
     40 {
     41     fx[u]=0;sz[u]=1;
     42     for(int k=f1[u];k;k=e[k].nxt)
     43         if(!vis[e[k].to]&&e[k].to!=fa)
     44         {
     45             getroot(e[k].to,u);
     46             fx[u]=max(fx[u],sz[e[k].to]);
     47             sz[u]+=sz[e[k].to];
     48         }
     49     fx[u]=max(fx[u],sum-sz[u]);
     50     if(fx[u]<fx[root])   root=u;
     51 }
     52 void getsz(int u,int fa)
     53 {
     54     sz[u]=1;
     55     for(int k=f1[u];k;k=e[k].nxt)
     56         if(!vis[e[k].to]&&e[k].to!=fa)
     57         {
     58             getsz(e[k].to,u);
     59             sz[u]+=sz[e[k].to];
     60         }
     61 }
     62 void getdeep(int u,int fa)
     63 {
     64     xx[root].push_back(P(dep[u],nowsec));
     65     for(int k=f1[u];k;k=e[k].nxt)
     66         if(!vis[e[k].to]&&e[k].to!=fa)
     67         {
     68             dep[e[k].to]=dep[u]+e[k].d;
     69             getdeep(e[k].to,u);
     70         }
     71 }
     72 void gdep(LL u)
     73 {
     74     int now=0;xx[root].push_back(P(dep[u],0));
     75     for(int k=f1[u];k;k=e[k].nxt)
     76         if(!vis[e[k].to])
     77         {
     78             dep[e[k].to]=dep[u]+e[k].d;
     79             nowsec=++now;
     80             getdeep(e[k].to,u);
     81         }
     82 }
     83 void solve(int u)
     84 {
     85     vis[u]=1;
     86     for(int k=f1[u];k;k=e[k].nxt)
     87         if(!vis[e[k].to])
     88         {
     89             getsz(e[k].to,0);sum=sz[e[k].to];
     90             root=0;getroot(e[k].to,0);
     91             dep[root]=0;gdep(root);
     92             solve(root);
     93         }
     94 }
     95 int main()
     96 {
     97     int i,j,u,v,l,ed;Info t;
     98     fx[0]=0x3f3f3f3f;
     99     scanf("%d%d",&n,&k);
    100     for(i=1;i<n;i++)
    101     {
    102         scanf("%d%d%d",&u,&v,&l);
    103         e[++ne].to=v;e[ne].nxt=f1[u];e[ne].d=l;f1[u]=ne;
    104         e[++ne].to=u;e[ne].nxt=f1[v];e[ne].d=l;f1[v]=ne;
    105     }
    106     sum=n;getroot(1,0);
    107     dep[root]=0;gdep(root);
    108     solve(root);
    109     for(i=1;i<=n;i++)    sort(xx[i].begin(),xx[i].end());
    110     for(i=1;i<=n;i++)
    111     {
    112         ed=xx[i].size()-1;
    113         nowed[i].reserve(ed+1);
    114         for(j=0;j<ed;j++)
    115         {
    116             nowed[i][j]=ed;
    117             q.push(Info(xx[i][ed].first+xx[i][j].first,i,j));
    118         }
    119     }
    120     for(i=1;i<=k;)
    121     {
    122         t=q.top();q.pop();
    123         if(xx[t.nn][t.l].second!=xx[t.nn][nowed[t.nn][t.l]].second)
    124         {
    125             ++i;
    126             printf("%lld
    ",t.ans);
    127         }
    128         --nowed[t.nn][t.l];
    129         if(nowed[t.nn][t.l]>t.l)
    130         {
    131             q.push(Info(xx[t.nn][nowed[t.nn][t.l]].first+xx[t.nn][t.l].first,t.nn,t.l));
    132         }
    133     }
    134     return 0;
    135 }
    View Code

    想想都知道不对啊。。。复杂度肯定不对的啊。。。。。毫不意外地T掉了,卡常也没用,不知道是不是特殊设计的数据

    然后去看了题解,有了新思路:对于任一个点搞出的vector,都不进行排序,这样的话其内部就是按子树编号排序的。

    如果以其中某一个点作为路径的一个端点,那么另外一个点就可以从这个vector里面除了子树编号与其相同的那一段以外的几段中选。

    考虑与超级钢琴类似的做法,那么只需要一个rmq就可以解决了

    我先用st表写rmq,然后无限MLE。。。。(我做的是n<=200000)其中还涉及了一些关于vector的奇妙操作,但是并没有拯救我

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<vector>
      4 #include<queue>
      5 #include<map>
      6 using namespace std;
      7 typedef long long LL;
      8 typedef pair<LL,int> P;
      9 struct E
     10 {
     11     int to,nxt,d;
     12 }e[400100];
     13 int f1[200100],n,k,ne;
     14 vector<P> xx[200100];
     15 //表示i点管辖的连通块内各点到自身的距离(second表示子树编号)
     16 vector<int> rmq[200100][19];
     17 vector<int> st,ed;
     18 //表示i点管辖的连通块内各个子树编号对应的xx内始、终位置
     19 int fx[200100],root,sz[200100],sum,nowsec;
     20 int lft[30],log2x[200100];
     21 LL dep[200010];
     22 bool vis[200100];
     23 struct Info
     24 {
     25     LL ans;int nn,l,r,anspos,pos;
     26     Info(){}
     27     Info(LL a,int b,int c,int d,int e,int f)
     28         :ans(a),nn(b),l(c),r(d),anspos(e),pos(f)
     29     {}
     30     friend bool operator<(const Info &a,const Info &b)
     31     {
     32         return a.ans<b.ans;
     33     }
     34 };
     35 priority_queue<Info> q;
     36 void getroot(int u,int fa)
     37 {
     38     fx[u]=0;sz[u]=1;
     39     for(int k=f1[u];k;k=e[k].nxt)
     40         if(!vis[e[k].to]&&e[k].to!=fa)
     41         {
     42             getroot(e[k].to,u);
     43             fx[u]=max(fx[u],sz[e[k].to]);
     44             sz[u]+=sz[e[k].to];
     45         }
     46     fx[u]=max(fx[u],sum-sz[u]);
     47     if(fx[u]<fx[root])   root=u;
     48 }
     49 void getsz(int u,int fa)
     50 {
     51     sz[u]=1;
     52     for(int k=f1[u];k;k=e[k].nxt)
     53         if(!vis[e[k].to]&&e[k].to!=fa)
     54         {
     55             getsz(e[k].to,u);
     56             sz[u]+=sz[e[k].to];
     57         }
     58 }
     59 void getdeep(int u,int fa)
     60 {
     61     xx[root].push_back(P(dep[u],nowsec));
     62     for(int k=f1[u];k;k=e[k].nxt)
     63         if(!vis[e[k].to]&&e[k].to!=fa)
     64         {
     65             dep[e[k].to]=dep[u]+e[k].d;
     66             getdeep(e[k].to,u);
     67         }
     68 }
     69 void gdep(LL u)
     70 {
     71     int now=0;xx[root].push_back(P(dep[u],0));
     72     for(int k=f1[u];k;k=e[k].nxt)
     73         if(!vis[e[k].to])
     74         {
     75             dep[e[k].to]=dep[u]+e[k].d;
     76             nowsec=++now;
     77             getdeep(e[k].to,u);
     78         }
     79 }
     80 void solve(int u)
     81 {
     82     vis[u]=1;
     83     for(int k=f1[u];k;k=e[k].nxt)
     84         if(!vis[e[k].to])
     85         {
     86             getsz(e[k].to,0);sum=sz[e[k].to];
     87             root=0;getroot(e[k].to,0);
     88             dep[root]=0;gdep(root);
     89             solve(root);
     90         }
     91 }
     92 int getmaxpos(int i,int l,int r)
     93 {
     94     int t=log2x[r-l+1];
     95     return xx[i][rmq[i][t][l]]>xx[i][rmq[i][t][r-lft[t]+1]] ?
     96         rmq[i][t][l]
     97         :rmq[i][t][r-lft[t]+1];
     98 }
     99 int main()
    100 {
    101     int i,j,j2,u,v,l,r,pos,nx;Info t;
    102     fx[0]=0x3f3f3f3f;lft[0]=1;
    103     for(i=1;i<20;i++)    lft[i]=lft[i-1]<<1;
    104     for(j=0,i=1;i<=200000;i++)
    105     {
    106         if(i>=lft[j+1])  ++j;
    107         log2x[i]=j;
    108     }
    109     scanf("%d%d",&n,&k);
    110     for(i=1;i<n;i++)
    111     {
    112         scanf("%d%d%d",&u,&v,&l);
    113         e[++ne].to=v;e[ne].nxt=f1[u];e[ne].d=l;f1[u]=ne;
    114         e[++ne].to=u;e[ne].nxt=f1[v];e[ne].d=l;f1[v]=ne;
    115     }
    116     sum=n;getroot(1,0);
    117     dep[root]=0;gdep(root);
    118     solve(root);
    119     for(i=1;i<=n;i++)
    120     {
    121         nx=xx[i].size();
    122         for(j=0;j<19;j++)    rmq[i][j].reserve(nx),rmq[i][j].resize(nx);
    123         st.clear();st.reserve(nx);st.resize(nx);
    124         ed.clear();ed.reserve(nx);ed.resize(nx);
    125         for(j=0;j<nx;j++)    rmq[i][0][j]=j;
    126         for(j2=1;j2<19;j2++)
    127             for(j=0;j<nx-lft[j2]+1;j++)
    128                 if(xx[i][rmq[i][j2-1][j]]>xx[i][rmq[i][j2-1][j+lft[j2-1]]])
    129                     rmq[i][j2][j]=rmq[i][j2-1][j];
    130                 else
    131                     rmq[i][j2][j]=rmq[i][j2-1][j+lft[j2-1]];
    132         for(j=0;j<nx;j++)
    133         {
    134             if(st[xx[i][j].second]==0)
    135                 st[xx[i][j].second]=j;
    136             ed[xx[i][j].second]=j;
    137         }
    138         for(j=0;j<nx;j++)
    139         {
    140             l=st[xx[i][j].second];r=ed[xx[i][j].second];
    141             if(l>0)
    142             {
    143                 pos=getmaxpos(i,0,l-1);
    144                 q.push(Info(xx[i][j].first+xx[i][pos].first,i,0,l-1,pos,j));
    145             }
    146             if(r<nx-1)
    147             {
    148                 pos=getmaxpos(i,r+1,nx-1);
    149                 q.push(Info(xx[i][j].first+xx[i][pos].first,i,r+1,nx-1,pos,j));
    150             }
    151         }
    152     }
    153     for(i=1;i<=k;i++)
    154     {
    155         t=q.top();q.pop();
    156         printf("%lld
    ",t.ans);
    157         if(t.anspos>t.l)
    158         {
    159             pos=getmaxpos(t.nn,t.l,t.anspos-1);
    160             q.push(Info(xx[t.nn][t.pos].first+xx[t.nn][pos].first,t.nn,t.l,t.anspos-1,pos,t.pos));
    161         }
    162         if(t.anspos<t.r)
    163         {
    164             pos=getmaxpos(t.nn,t.anspos+1,t.r);
    165             q.push(Info(xx[t.nn][t.pos].first+xx[t.nn][pos].first,t.nn,t.anspos+1,t.r,pos,t.pos));
    166         }
    167         t=q.top();q.pop();
    168         if(t.anspos>t.l)
    169         {
    170             pos=getmaxpos(t.nn,t.l,t.anspos-1);
    171             q.push(Info(xx[t.nn][t.pos].first+xx[t.nn][pos].first,t.nn,t.l,t.anspos-1,pos,t.pos));
    172         }
    173         if(t.anspos<t.r)
    174         {
    175             pos=getmaxpos(t.nn,t.anspos+1,t.r);
    176             q.push(Info(xx[t.nn][t.pos].first+xx[t.nn][pos].first,t.nn,t.anspos+1,t.r,pos,t.pos));
    177         }
    178     }
    179     return 0;
    180 }
    View Code

    迫不得已只好换成线段树。。。终于A掉了(说起来新写法最后(x,y)和(y,x)会分别出现一次,要判掉)

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<vector>
      4 #include<queue>
      5 #include<map>
      6 using namespace std;
      7 typedef long long LL;
      8 typedef pair<LL,int> P;
      9 struct E
     10 {
     11     int to,nxt,d;
     12 }e[400100];
     13 int f1[200100],n,k,ne;
     14 vector<P> xx[200100];
     15 //表示i点管辖的连通块内各点到自身的距离(second表示子树编号)
     16 vector<int> rmq[200100];
     17 vector<int> st,ed;
     18 //表示i点管辖的连通块内各个子树编号对应的xx内始、终位置
     19 int fx[200100],root,sz[200100],sum,nowsec;
     20 int lft[30],log2x[200100];
     21 LL dep[200010];
     22 bool vis[200100];
     23 struct Info
     24 {
     25     LL ans;int nn,l,r,anspos,pos;
     26     Info(){}
     27     Info(LL a,int b,int c,int d,int e,int f)
     28         :ans(a),nn(b),l(c),r(d),anspos(e),pos(f)
     29     {}
     30     friend bool operator<(const Info &a,const Info &b)
     31     {
     32         return a.ans<b.ans;
     33     }
     34 };
     35 priority_queue<Info> q;
     36 void getroot(int u,int fa)
     37 {
     38     fx[u]=0;sz[u]=1;
     39     for(int k=f1[u];k;k=e[k].nxt)
     40         if(!vis[e[k].to]&&e[k].to!=fa)
     41         {
     42             getroot(e[k].to,u);
     43             fx[u]=max(fx[u],sz[e[k].to]);
     44             sz[u]+=sz[e[k].to];
     45         }
     46     fx[u]=max(fx[u],sum-sz[u]);
     47     if(fx[u]<fx[root])   root=u;
     48 }
     49 void getsz(int u,int fa)
     50 {
     51     sz[u]=1;
     52     for(int k=f1[u];k;k=e[k].nxt)
     53         if(!vis[e[k].to]&&e[k].to!=fa)
     54         {
     55             getsz(e[k].to,u);
     56             sz[u]+=sz[e[k].to];
     57         }
     58 }
     59 void getdeep(int u,int fa)
     60 {
     61     xx[root].push_back(P(dep[u],nowsec));
     62     for(int k=f1[u];k;k=e[k].nxt)
     63         if(!vis[e[k].to]&&e[k].to!=fa)
     64         {
     65             dep[e[k].to]=dep[u]+e[k].d;
     66             getdeep(e[k].to,u);
     67         }
     68 }
     69 void gdep(LL u)
     70 {
     71     int now=0;xx[root].push_back(P(dep[u],0));
     72     for(int k=f1[u];k;k=e[k].nxt)
     73         if(!vis[e[k].to])
     74         {
     75             dep[e[k].to]=dep[u]+e[k].d;
     76             nowsec=++now;
     77             getdeep(e[k].to,u);
     78         }
     79 }
     80 void solve(int u)
     81 {
     82     vis[u]=1;
     83     for(int k=f1[u];k;k=e[k].nxt)
     84         if(!vis[e[k].to])
     85         {
     86             getsz(e[k].to,0);sum=sz[e[k].to];
     87             root=0;getroot(e[k].to,0);
     88             dep[root]=0;gdep(root);
     89             solve(root);
     90         }
     91 }
     92 #define mid ((l+r)>>1)
     93 #define lc (num<<1)
     94 #define rc (num<<1|1)
     95 void build(int i,int l,int r,int num)
     96 {
     97     if(l==r)    {rmq[i][num]=l;return;}
     98     build(i,l,mid,lc);build(i,mid+1,r,rc);
     99     rmq[i][num]=xx[i][rmq[i][lc]]>xx[i][rmq[i][rc]]?rmq[i][lc]:rmq[i][rc];
    100 }
    101 int L,R;
    102 int query(int i,int l,int r,int num)
    103 {
    104     if(L<=l&&r<=R)    return rmq[i][num];
    105     if(L<=mid&&mid<R)
    106     {
    107         int t1=query(i,l,mid,lc),t2=query(i,mid+1,r,rc);
    108         return xx[i][t1]>xx[i][t2]?t1:t2;
    109     }
    110     else if(L<=mid)  return query(i,l,mid,lc);
    111     else if(mid<R)   return query(i,mid+1,r,rc);
    112     else    return 0;
    113 }
    114 int main()
    115 {
    116     int i,j,j2,u,v,l,r,pos,nx;Info t;
    117     fx[0]=0x3f3f3f3f;lft[0]=1;
    118     for(i=1;i<30;i++)    lft[i]=lft[i-1]<<1;
    119     for(j=0,i=1;i<=200000;i++)
    120     {
    121         if(i>=lft[j+1])  ++j;
    122         log2x[i]=j;
    123     }
    124     scanf("%d%d",&n,&k);
    125     for(i=1;i<n;i++)
    126     {
    127         scanf("%d%d%d",&u,&v,&l);
    128         e[++ne].to=v;e[ne].nxt=f1[u];e[ne].d=l;f1[u]=ne;
    129         e[++ne].to=u;e[ne].nxt=f1[v];e[ne].d=l;f1[v]=ne;
    130     }
    131     sum=n;getroot(1,0);
    132     dep[root]=0;gdep(root);
    133     solve(root);
    134     for(i=1;i<=n;i++)
    135     {
    136         nx=xx[i].size();
    137         st.clear();st.reserve(nx);st.resize(nx);
    138         ed.clear();ed.reserve(nx);ed.resize(nx);
    139         rmq[i].reserve(lft[log2x[nx]+2]);rmq[i].resize(lft[log2x[nx]+2]);
    140         build(i,0,nx-1,1);
    141         for(j=0;j<nx;j++)
    142         {
    143             if(st[xx[i][j].second]==0)
    144                 st[xx[i][j].second]=j;
    145             ed[xx[i][j].second]=j;
    146         }
    147         for(j=0;j<nx;j++)
    148         {
    149             l=st[xx[i][j].second];r=ed[xx[i][j].second];
    150             if(l>0)
    151             {
    152                 L=0,R=l-1,pos=query(i,0,nx-1,1);
    153                 q.push(Info(xx[i][j].first+xx[i][pos].first,i,0,l-1,pos,j));
    154             }
    155             if(r<nx-1)
    156             {
    157                 L=r+1,R=nx-1,pos=query(i,0,nx-1,1);
    158                 q.push(Info(xx[i][j].first+xx[i][pos].first,i,r+1,nx-1,pos,j));
    159             }
    160         }
    161     }
    162     for(i=1;i<=k;i++)
    163     {
    164         t=q.top();q.pop();
    165         printf("%lld
    ",t.ans);
    166         if(t.anspos>t.l)
    167         {
    168             L=t.l,R=t.anspos-1,pos=query(t.nn,0,xx[t.nn].size()-1,1);
    169             q.push(Info(xx[t.nn][t.pos].first+xx[t.nn][pos].first,t.nn,t.l,t.anspos-1,pos,t.pos));
    170         }
    171         if(t.anspos<t.r)
    172         {
    173             L=t.anspos+1,R=t.r,pos=query(t.nn,0,xx[t.nn].size()-1,1);
    174             q.push(Info(xx[t.nn][t.pos].first+xx[t.nn][pos].first,t.nn,t.anspos+1,t.r,pos,t.pos));
    175         }
    176         t=q.top();q.pop();
    177         if(t.anspos>t.l)
    178         {
    179             L=t.l,R=t.anspos-1,pos=query(t.nn,0,xx[t.nn].size()-1,1);
    180             q.push(Info(xx[t.nn][t.pos].first+xx[t.nn][pos].first,t.nn,t.l,t.anspos-1,pos,t.pos));
    181         }
    182         if(t.anspos<t.r)
    183         {
    184             L=t.anspos+1,R=t.r,pos=query(t.nn,0,xx[t.nn].size()-1,1);
    185             q.push(Info(xx[t.nn][t.pos].first+xx[t.nn][pos].first,t.nn,t.anspos+1,t.r,pos,t.pos));
    186         }
    187     }
    188     return 0;
    189 }

    还有两点:

    1.这题还有一个写法,就是先二分答案找第k大(由于判断价值小于某个给定值的点对数可以用点分容斥做,比较容易),然后再一遍点分把小于这个第k大的全部搞出来(好像是启发式)

    2.按照我这个写法,好像可以把各个vector并到一个数组里,然后st表,就不会MLE了

  • 相关阅读:
    Python学习--not语句
    【图论】有向无环图的拓扑排序
    算法精解:DAG有向无环图
    Python xrange() 函数
    自然语言处理课程(二):Jieba分词的原理及实例操作
    Jieba分词原理与解析
    ios面试题整理
    OC语言Block和协议
    OC内存管理
    IOS 开发-- 常用-- 核心代码
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8606072.html
Copyright © 2011-2022 走看看