码迷,mamicode.com
首页 > 其他好文 > 详细

csp-s模拟测试58「Divisors」·「Market」·「Dash Speed」?

时间:2019-10-04 22:41:39      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:speed   void   位置   RKE   bsp   else   约数   联通   ade   

A. Divisors


 
大概平均下来每个数也就几千约数吧....,直接筛

 

B. Market


可以把时间离线下来,

考试没有想到将询问离线,用数组存算了算只能过200的点,拿了70

事实上背包后直接二分就好。。。

 

C. Dash Speed


好题,想到以前的一道题影子。

考场用单调队列多QJ了20分,然而没有想到并查集

线段树上分治?????

线段树上的节点表示在该权值在该区间内的边,每个节点开个vector即可

那么考虑区间查询和单点修改,

对于每个叶子节点,我们从上到下所经历的边其实就是可行的边

对于每个节点维护并查集,该联通块的最长直径和两个端点

在两个联通块相连时就是6种情况

即原直径或两联通块的端点所连的直径

但是对于每个点我们清空并查集会T,

那么我们采用按秩合并....

就是对每个节点编个排名,然后排名小的连向排名的节点,

然后我们开个栈,记录每次新连边后更改信息

void deld(int now){
    while(top>now){
          fa[st[top].to]=st[top].to;
          del[st[top].fa]-=del[st[top].to];
          len[st[top].fa]=st[top].val;
          lx[st[top].fa]=st[top].dian1;
          rx[st[top].fa]=st[top].dian2;
          top--;
    }
}

因为我们是将两联通块的fa节点相连,所以撤去后,儿子节点指向自己,父亲节点的del要减去

然后len,及直径两端点修改回原来的。

然后以为是栈,所以分治完后清空就好了。

因为倍增LCA超时了,所以改为ST求LCA,O(1)查询,跑的飞快

void DFS(int x,int father){
     pre[++dep]=x;R[dep]=deep[x];fir[x]=dep;
     for(int i=head[x];i;i=e[i].n){
         int to=e[i].to;
         if(to==father)continue;
         deep[to]=deep[x]+1;
         DFS(to,x);
         pre[++dep]=x;R[dep]=deep[x];
     }
}
void ST(){ 
     logg[0]=-1;
     for(int i=1;i<=dep;++i)logg[i]=logg[i>>1]+1;
     for(int j=1;j<=dep;++j)faa[j][0]=j;
     for(int j=1;(1<<j)<=dep;++j){
         for(int i=1;i+(1<<j)-1<=dep;++i){
             int x=faa[i][j-1];int y=faa[i+(1<<(j-1))][j-1];
             if(R[x]<R[y])faa[i][j]=x;
             else faa[i][j]=y;
         }
     }
}

 

每个节点遍历时添进pre数组里,回溯时也要添R数组记录深度,fir记录每个值的最小出现位置

倍增找两节点中深度最小的节点,注意现在节点是pre的序列节点

查询找fir[x],fir[y]这段区间的最小深度对应的节点

 

 

csp-s模拟测试58「Divisors」·「Market」·「Dash Speed」?

标签:speed   void   位置   RKE   bsp   else   约数   联通   ade   

原文地址:https://www.cnblogs.com/Wwb123/p/11623346.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!