zoukankan      html  css  js  c++  java
  • bzoj2006 [ NOI2010 ] && bzoj3784 --点分治+线段树+堆

    bzoj2006:

    定义一个四元组{x,l,r,w},表示左端点在x,右端点在[l,r]的超级和弦的最大美妙度在将w作为右端点时取到,w可以用前缀和+线段树/ST表求出。

    对于每个i,我们将{i,i+L-1,i+R-1,w}放入一个大根堆中,每次取出美妙度最大的一个加到答案中,并将{i,l,w-1,x},{i,w+1,r,x}放入堆中。

    这样就相当于将左端点在i、右端点在w的超级和弦去掉。做k次就可以了。

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 #include<algorithm>
     6 using namespace std;
     7 inline char Nc(){
     8     static char buf[100000],*p1=buf,*p2=buf;
     9     if(p1==p2){
    10         p2=(p1=buf)+fread(buf,1,100000,stdin);
    11         if(p1==p2)return EOF;
    12     }
    13     return *p1++;
    14 }
    15 inline void Read(int& x){
    16     char c=Nc(),b=1;
    17     for(;c<'0'||c>'9';c=Nc())if(c=='-')b=-1;
    18     for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=Nc());x*=b;
    19 }
    20 inline int _Max(int x,int y){return x<y?y:x;}
    21 inline int _Min(int x,int y){return x<y?x:y;}
    22 #define N 500010
    23 #define INF 2147483647
    24 int i,j,k,n,m,c[N<<2],s[N],x,L,R,t[N<<2];
    25 struct G{
    26     int x,l,r,w;
    27     G(){}
    28     G(int x,int l,int r,int w):x(x),l(l),r(r),w(w){}
    29     bool operator<(G a)const{
    30         return s[w]-s[x-1]<s[a.w]-s[a.x-1];
    31     }
    32 }tmp;
    33 priority_queue<G>q;
    34 long long Ans;
    35 inline int Query(int Node,int l,int r,int L,int R){
    36     if(l>R||r<L)return 0;
    37     if(l>=L&&r<=R)return Node;
    38     int Mid=l+r>>1;
    39     int Q1=Query(Node<<1,l,Mid,L,R),Q2=Query(Node<<1|1,Mid+1,r,L,R);
    40     return c[Q1]>c[Q2]?Q1:Q2;
    41 }
    42 inline void Build(int Node,int l,int r){ 
    43     if(l==r){
    44         c[Node]=s[l];
    45         t[Node]=l;
    46         return;
    47     }
    48     int Mid=l+r>>1;
    49     Build(Node<<1,l,Mid);
    50     Build(Node<<1|1,Mid+1,r);
    51     if(c[Node<<1]>c[Node<<1|1])c[Node]=c[Node<<1],t[Node]=t[Node<<1];else
    52     c[Node]=c[Node<<1|1],t[Node]=t[Node<<1|1];
    53 }
    54 int main()
    55 {
    56     Read(n);Read(k);Read(L);Read(R);
    57     for(i=1;i<=n;i++)Read(x),s[i]=s[i-1]+x;
    58     Build(1,1,n);c[0]=-INF;
    59     for(i=1;i+L-1<=n;i++)q.push(G(i,i+L-1,_Min(i+R-1,n),t[Query(1,1,n,i+L-1,_Min(i+R-1,n))]));
    60     while(k--){
    61         tmp=q.top();q.pop();
    62         Ans+=s[tmp.w]-s[tmp.x-1]; 
    63         if(tmp.w>tmp.l)q.push(G(tmp.x,tmp.l,tmp.w-1,t[Query(1,1,n,tmp.l,tmp.w-1)]));
    64         if(tmp.w<tmp.r)q.push(G(tmp.x,tmp.w+1,tmp.r,t[Query(1,1,n,tmp.w+1,tmp.r)]));
    65     }
    66     printf("%lld",Ans);
    67     return 0;
    68 }
    bzoj2006

    bzoj3784:

    这题是bzoj2006的树上版本。考虑点分治。分治到一个点时,将所有点到它的距离d求出,那么一个子树中的点的d加上另一个子树中的点的d就是一条路径。

    将dfs到的点依次加入一个序列,那么序列中每个点能到的所有点就是一个区间[l,r],就可以转化为bzoj2006了。

    具体看代码。

    代码:

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<queue>
      5 using namespace std;
      6 inline char Nc(){
      7     static char buf[100000],*p1=buf,*p2=buf;
      8     if(p1==p2){
      9         p2=(p1=buf)+fread(buf,1,100000,stdin);
     10         if(p1==p2)return EOF;
     11     }
     12     return *p1++;
     13 }
     14 inline void Read(int& x){
     15     char c=Nc(),b=1;
     16     for(;c<'0'||c>'9';c=Nc())if(c=='-')b=-1;
     17     for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=Nc());x*=b;
     18 }
     19 inline int _Max(int x,int y){return x>y?x:y;}
     20 #define N 50010
     21 #define INF 2147483647
     22 struct Edge{
     23     int t,nx,w;
     24 }e[N<<1];
     25 int i,j,k,n,Cnt,m,l[N<<5],r[N<<5],x,y,z,L,R,c[N<<6],Num,p[N<<6],a[N<<5],h[N],f[N],d[N],Size[N],Rt,Sum;
     26 bool b[N];
     27 struct G{
     28     int l,r,w,t;
     29     G(){}
     30     G(int l,int r,int w,int t):l(l),r(r),w(w),t(t){}
     31     bool operator<(G b)const{
     32         return a[t]+w<a[b.t]+b.w;
     33     }
     34 }tmp;
     35 priority_queue<G>q;
     36 inline void Add(int x,int y,int z){e[++Num].t=y;e[Num].w=z;e[Num].nx=h[x];h[x]=Num;}
     37 inline void Get_root(int x,int F){
     38     f[x]=0;Size[x]=1;
     39     for(int i=h[x];i;i=e[i].nx){
     40         int v=e[i].t;
     41         if(!b[v]&&v!=F){
     42             Get_root(v,x);
     43             Size[x]+=Size[v];
     44             f[x]=_Max(f[x],Size[v]);
     45         }
     46     }
     47     f[x]=_Max(f[x],Sum-Size[x]);
     48     if(f[x]<f[Rt])Rt=x;
     49 }
     50 inline void Dfs(int x,int F){
     51     a[++Cnt]=d[x];l[Cnt]=L;r[Cnt]=R;
     52     for(int i=h[x];i;i=e[i].nx){
     53         int v=e[i].t;
     54         if(!b[v]&&v!=F)d[v]=d[x]+e[i].w,Dfs(v,x);
     55     }
     56 }
     57 inline void Solve(int x){
     58     a[++Cnt]=0;d[x]=0;L=R=Cnt;b[x]=1;
     59     for(int i=h[x];i;i=e[i].nx){
     60         int v=e[i].t;
     61         if(!b[v])d[v]=e[i].w,Dfs(v,x),R=Cnt;
     62     }
     63     for(int i=h[x];i;i=e[i].nx){
     64         int v=e[i].t;
     65         if(!b[v]){
     66             f[Rt=0]=Size[v]+1;Sum=Size[v];
     67             Get_root(v,x);
     68             Solve(Rt);
     69         }
     70     }
     71 }
     72 inline void Build(int Node,int l,int r){
     73     if(l==r){
     74         c[Node]=a[l];
     75         p[Node]=l;
     76         return;
     77     }
     78     int Mid=l+r>>1;
     79     Build(Node<<1,l,Mid);
     80     Build(Node<<1|1,Mid+1,r);
     81     if(c[Node<<1]>c[Node<<1|1])c[Node]=c[Node<<1],p[Node]=p[Node<<1];else
     82     c[Node]=c[Node<<1|1],p[Node]=p[Node<<1|1];
     83 }
     84 inline int Query(int Node,int l,int r,int L,int R){
     85     if(l>R||r<L)return 0;
     86     if(l>=L&&r<=R)return Node;
     87     int Mid=l+r>>1;
     88     int Q1=Query(Node<<1,l,Mid,L,R),Q2=Query(Node<<1|1,Mid+1,r,L,R);
     89     return c[Q1]>c[Q2]?Q1:Q2;
     90 }
     91 int main()
     92 {
     93     Read(n);Read(m);
     94     for(i=1;i<n;i++)Read(x),Read(y),Read(z),Add(x,y,z),Add(y,x,z);
     95     f[Rt=0]=n+1;Sum=n;Get_root(1,0);
     96     Solve(Rt);
     97     Build(1,1,Cnt);c[0]=-INF;
     98     for(i=1;i<=Cnt;i++)if(l[i])q.push(G(l[i],r[i],a[i],p[Query(1,1,Cnt,l[i],r[i])]));
     99     while(m--){
    100         tmp=q.top();q.pop();
    101         printf("%d
    ",tmp.w+a[tmp.t]);
    102         if(tmp.t>tmp.l)q.push(G(tmp.l,tmp.t-1,tmp.w,p[Query(1,1,Cnt,tmp.l,tmp.t-1)]));
    103         if(tmp.t<tmp.r)q.push(G(tmp.t+1,tmp.r,tmp.w,p[Query(1,1,Cnt,tmp.t+1,tmp.r)]));
    104     }
    105     return 0;
    106 }
    bzoj3784
  • 相关阅读:
    pytest
    pytest 跳过测试用例 skip
    pytest
    pytest -allure标记用例级别severity
    pytest-
    pytest-分布式执行(pytest-xdist)
    4、win10搭建easy-mock平台
    pandas日期缺失,空值填充方法
    Pandas拼接操作(concat,merge,join和append)的区别
    关于docker容器和镜像的区别
  • 原文地址:https://www.cnblogs.com/gjghfd/p/6432226.html
Copyright © 2011-2022 走看看