cf div2_199_E

题目的意思是给你一颗树n(100000)个树的几点,然后开始树都是白色的,根的颜色是红色的,然后给你m个操作,1  x操作表示把x这个点变成红色,2 x询问x到最近红色点的距离,我听闻有3种解法(分割+点的分治+轻重边)

解法1 对于m(100000)个询问分成sqrt(m) 块,然后在每个块内,如果是更改操作,把相应点放入临时数组,对于查询,先看原图最小距离,和临时数组里面点的最小值(通过lca 处理)对于每个块之间用用一次bfs 把临时数组里面的值更新给原图,可以得出负责度为(sqrt(m)*n)开始写的时候无限tle 后面只对于更改分块,因为就更改会改变临时数组的

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#define M 101000
#define inf 0x3f3f3f3f
using namespace std;
struct G{
    int head[M],en;
    struct E{
        int u,v,next;
    }e[M<<2];
    void init(){
        memset(head,-1,sizeof(head));en=0;
    }
    void add(int u,int v){
        e[en].u=u;e[en].v=v;e[en].next=head[u];head[u]=en++;
    }
}g1;
int dex[M*2];
void init_dex(){
    dex[0]=-1;
    for(int i=1;i<M*2-1;i++){
        if(i&(i-1)) dex[i]=dex[i-1];
        else dex[i]=dex[i-1]+1;
    }
}
int aa[M*2],bb[M*2],en;
struct R{
    int head[M*2],raa[M*2][20],rbb[M*2][20];
    void init(){
        memset(rbb,inf,sizeof(rbb));
        memset(head,-1,sizeof(head));
        for(int i=0;i<en;i++){
            int u=aa[i];
            if(head[u]==-1){
                head[u]=i;
            }
            raa[i][0]=aa[i];
            rbb[i][0]=bb[i];
        }
        for(int i=1;(1<<i)<=en;i++){
            for(int j=0;j+(1<<i)<en;j++){
                int next=j+(1<<(i-1));
                if(rbb[j][i-1]<rbb[next][i-1]){
                    rbb[j][i]=rbb[j][i-1];
                    raa[j][i]=raa[j][i-1];
                }
                else{
                    rbb[j][i]=rbb[next][i-1];
                    raa[j][i]=raa[next][i-1];
                }
            }
        }
    }
    int query(int l,int r){
        l=head[l];r=head[r];
        if(l>r) swap(l,r);
        int p1=dex[r-l+1];
        r-=(1<<(p1))-1;
        if(rbb[l][p1]<=rbb[r][p1]) return raa[l][p1];
        return raa[r][p1];
    }
}rmq;
int dis[M];
int is_red[M];
void dfs1(int u,int p,int level){
    dis[u]=level;
    aa[en]=u;
    bb[en++]=level;
    for(int i=g1.head[u];~i;i=g1.e[i].next){
        int v=g1.e[i].v;
        if(v==p) continue;
        dfs1(v,u,level+1);
        aa[en]=u;
        bb[en++]=level;
    }
}
int block[M];
int tmin[M];
int my_queue[M],qh,qt;
void dfs2(int u,int p,int level){
    if(tmin[u]>level) tmin[u]=level;
    else return ;
    for(int i=g1.head[u];~i;i=g1.e[i].next){
        int v=g1.e[i].v;
        if(v==p) continue;
        if(is_red[v]) continue;
        dfs2(v,u,level+1);
    }
}
void bfs(){
    while(qt>=qh){
        int u=my_queue[qh++];
        if(is_red[u]==1) tmin[u]=0;
        for(int i=g1.head[u];~i;i=g1.e[i].next){
            int v=g1.e[i].v;
            if(tmin[v]>tmin[u]+1){
                tmin[v]=tmin[u]+1;
                my_queue[++qt]=v;
            }
        }
    }
}
int main(){
    init_dex();
    int n,m;while(~scanf("%d%d",&n,&m)){
        g1.init();
        for(int i=0;i<n-1;i++){
            int u,v;scanf("%d%d",&u,&v);
            g1.add(u,v);g1.add(v,u);
        }
        en=0;
        dfs1(1,-1,0);
        rmq.init();
        for(int i=1;i<=n;i++){
            tmin[i]=dis[i];
        }
        int num=0;
        int flag=0;
        int siz=200;
        memset(is_red,0,sizeof(is_red));
        is_red[1]=1;
        for(int i=0;i<m;i++){
            int t1,t2;scanf("%d%d",&t1,&t2);
            if(t1==2){
                if(is_red[t2]){
                    puts("0");continue;
                }
                int ans=tmin[t2];
                for(int j=0;j<num;j++){
                    int tt=block[j];
                    int fa=rmq.query(t2,tt);
                    int t3=dis[t2]+dis[tt]-2*dis[fa];
                    if(t3<ans) ans=t3;
                }
                printf("%d\n",ans);
            }
            else{
                flag++;
                is_red[t2]=1;
                block[num++]=t2;
            }
            if(flag==siz){
                qh=0;qt=-1;
                for(int j=0;j<num;j++){
                    int t3=block[j];
                    my_queue[++qt]=t3;
                }
                bfs();
                flag=0;
                num=0;
            }
        }
    }
    return 0;
}

长度,780ms ac这个好像是官方提供的解

解法2 树点的分治 大神的思路自己模仿代码

#include<cstdio>
#include<cstring>
#include<iostream>
#define M 111000
#define inf 0x3f3f3f3f
using namespace std;
struct G1{
    int head[M],en;
    struct E{
        int u,v,next,flag;
    }e[M<<4];
    void init(){
        memset(head,-1,sizeof(head));en=0;
    }
    void add(int u,int v){
        e[en].flag=0;
        e[en].u=u;e[en].v=v;e[en].next=head[u];head[u]=en++;
    }
}g1;
struct G2{
    int head[M],en;
    struct E{
        int u,v,next,cost;
    }e[M<<6];
    void init(){
        memset(head,-1,sizeof(head));en=0;
    }
    void add(int u,int v,int cost){
        e[en].cost=cost;
        e[en].u=u;e[en].v=v;e[en].next=head[u];head[u]=en++;
    }
}g2;
int dis[M],cen,ms[M],son[M],siz;
void find_root(int u,int p){
    son[u]=1,ms[u]=0;
    for(int i=g1.head[u];~i;i=g1.e[i].next){
        int v=g1.e[i].v;
        if(v==p||g1.e[i].flag) continue;
        find_root(v,u);
        son[u]+=son[v];
        if(son[v]>ms[u]) ms[u]=son[v];
    }
    if(ms[u]<siz-son[u]) ms[u]=siz-son[u];
    if(ms[u]<ms[cen]){
        cen=u;
    }
}
void dfs(int u,int p,int pos){
    dis[u]=dis[p]+1;
    g2.add(u,pos,dis[u]);
    for(int i=g1.head[u];~i;i=g1.e[i].next){
        int v=g1.e[i].v;
        if(g1.e[i].flag||v==p) continue;
        dfs(v,u,pos);
    }
}
void divide(int pos){
    dis[0]=-1;
    dfs(pos,0,pos);
    for(int i=g1.head[pos];i!=-1;i=g1.e[i].next){
        g1.e[i^1].flag=1;
        if(g1.e[i].flag) continue;
        int v=g1.e[i].v;
        cen=0;ms[cen]=siz=son[v];
        find_root(v,-1);
        divide(cen);
    }
}
int ans[M];
void mark(int u){
    ans[u]=0;
    for(int i=g2.head[u];~i;i=g2.e[i].next){
        int v=g2.e[i].v;
        int cost=g2.e[i].cost;
        if(ans[v]>ans[u]+cost) ans[v]=ans[u]+cost;
    }
}
int query(int u){
    int ret=ans[u];
    for(int i=g2.head[u];~i;i=g2.e[i].next){
        int v=g2.e[i].v;
        int cost=g2.e[i].cost;
        if(ret>ans[v]+cost) ret=ans[v]+cost;
    }
    return ret;
}
int main(){
    int n,m;while(~scanf("%d%d",&n,&m)){
        g1.init();
        for(int i=0;i<n-1;i++){
            int u,v;scanf("%d%d",&u,&v);g1.add(u,v);g1.add(v,u);
        }
        siz=n;cen=0;ms[cen]=siz;
        find_root(1,-1);
        g2.init();
        divide(cen);
        memset(ans,inf,sizeof(ans));
        mark(1);
        for(int i=0;i<m;i++){
            int t1,t2;scanf("%d%d",&t1,&t2);
            if(t1==1){
                mark(t2);
            }
            else{
                int tt=query(t2);
                printf("%d\n",tt);
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
<div id="wea_rich_text_default_font" style="font-family:微软雅黑;font-size:12;"><p><img alt="" src="/weaver/weaver.file.FileDownload?fileid=aaa9aee4717d33272bd7ea028fa03118b693919f23b18febf9f6cee1158e8f4cf027542c71c8cf98d63770ccdf3bd1750e6b92e28c43dccd4" /></p><div class="ckeditor-html5-video" data-widget="html5video" style="text-align:left"><video controls="controls" src="/weaver/weaver.file.FileDownload?fileid=aad6f413f83191673980c5ee24b412880d6b9e8703caca411faec3276fe8133f5fa7e34630ca89ace63770ccdf3bd175071362141037cfb4e&download=1" style="max-width:100%"> </video></div><table border="1" cellpadding="1" style="width:500px;"> <tbody> <tr> <td style="padding: 1px;">1</td> <td style="padding: 1px;">1</td> </tr> <tr> <td style="padding: 1px;">2</td> <td style="padding: 1px;">2</td> </tr> <tr> <td style="padding: 1px;">3</td> <td style="padding: 1px;">3<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></td> </tr> </tbody></table><p>测试<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></p><p> </p><p>修改一下吧 qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq<img alt="" src="/weaver/weaver.file.FileDownload?fileid=a7617945ec5f52ec80aaa43ee8504de0a1b14d5eca4a98834494c85349762c626dec7ba8d0da277106ee600d27743f4e44f710fbddd167603" /></p></div>
06-01
这段代码是一个HTML页面的代码,其中包含了一张图片、一个视频、一个表格和一些文本内容。该HTML页面使用了一些样式,如字体和字号,以及一些链接。具体的代码解析如下: ``` <div id="wea_rich_text_default_font" style="font-family:微软雅黑;font-size:12;"> ``` 这是一个包含了样式信息的div标签,其中指定了字体为微软雅黑,字号为12。 ``` <p><img alt="" src="/weaver/weaver.file.FileDownload?fileid=aaa9aee4717d33272bd7ea028fa03118b693919f23b18febf9f6cee1158e8f4cf027542c71c8cf98d63770ccdf3bd1750e6b92e28c43dccd4" /></p> ``` 这是一个包含了一张图片的p标签,其中指定了图片的路径和alt属性为空。 ``` <div class="ckeditor-html5-video" data-widget="html5video" style="text-align:left"> <video controls="controls" src="/weaver/weaver.file.FileDownload?fileid=aad6f413f83191673980c5ee24b412880d6b9e8703caca411faec3276fe8133f5fa7e34630ca89ace63770ccdf3bd175071362141037cfb4e&download=1" style="max-width:100%"> </video> </div> ``` 这是一个包含了一个视频的div标签,其中指定了视频的路径和样式信息。视频使用了HTML5的video标签,并且指定了控件和最大宽度为100%。 ``` <table border="1" cellpadding="1" style="width:500px;"> <tbody> <tr> <td style="padding: 1px;">1</td> <td style="padding: 1px;">1</td> </tr> <tr> <td style="padding: 1px;">2</td> <td style="padding: 1px;">2</td> </tr> <tr> <td style="padding: 1px;">3</td> <td style="padding: 1px;">3<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></td> </tr> </tbody> </table> ``` 这是一个包含了一个表格的table标签,其中指定了表格的样式和边框为1像素。表格中包含了三行数据,每行数据有两列,第三行的第二列还包含了一个链接。 ``` <p>测试<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></p> ``` 这是一个包含了一个链接的p标签,其中指定了链接的路径和打开方式。 ``` <p> </p> ``` 这是一个空的p标签,用于在文本内容之间添加一个空行。 ``` <p>修改一下吧 qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq<img alt="" src="/weaver/weaver.file.FileDownload?fileid=a7617945ec5f52ec80aaa43ee8504de0a1b14d5eca4a98834494c85349762c626dec7ba8d0da277106ee600d27743f4e44f710fbddd167603" /></p> ``` 这是一个包含了一张图片的p标签,其中指定了图片的路径和alt属性为空。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值