BZOJ1095

动态点分治,先搞出重心树,对于重心树的每一个节点维护两个队q1,q2,前者维护当前子树到父重心(重心树中的父亲???)的距离,后者维护当前节点每一个出度的q1堆顶,再全局维护一个ans,即所有节点q2的最大值和次大值……
被坑点:
1、一开始求出第一个重心后,dfs要从重心开始搜!!!
2、 dep[x]+dep[y]-2*dep[lca(x,y)];注意要 2 !!!
3、开anc数组要开大一点!!!不然就会越界!!!本来开了17,后来发现循环时从17开始扫……
4、乱压行会死得很惨!!!注意优先级!!!

//http://www.cnblogs.com/juruolty/p/6502677.html
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#define maxn 100000+10
#define read(x) scanf("%d",&x)

using namespace std;
int i,j,dep[maxn],rot,c,now_sz,f[maxn],a[maxn],x,T,y,off_tot,n,m,head[maxn];
int anc[maxn][20],g[maxn]={9999999999},sz[maxn],vis[maxn];
char s[10];
struct xx{
    int v,next;
}b[maxn<<1];

struct heap{
    priority_queue<int> ad,del;
    void _push(int x){ad.push(x);};
    void _pop(int x){del.push(x);};
    int _top(){while (del.size()&&ad.top()==del.top()) ad.pop(),del.pop();return ad.top();}
    int get_two(){int a,b;return a=_top(),ad.pop(),b=_top(),_push(a),a+b;}
    int sz(){return ad.size()-del.size();}
}ans,q1[maxn],q2[maxn];//q1表示子树节点到父重心距离,
                       //q2表示子节点q1堆顶,
                       //ans表示所有重心q2堆顶 

void add(int u,int v)
{
    b[++m]=(xx){v,head[u]};
    head[u]=m;
}

int lca(int p,int q)
{
    if (dep[p]<dep[q])swap(p,q);
    for (int i=17;i>=0;--i)
      if (dep[p]-(1<<i)>=dep[q]) p=anc[p][i];
    if (p==q) return p;
    for (int i=17;i>=0;--i) 
      if (anc[p][i]^anc[q][i]) p=anc[p][i],q=anc[q][i];
    return anc[p][0];
}

int ds(int x,int y)
{
    return dep[x]+dep[y]-2*dep[lca(x,y)];
}

int cal(int x)//turn_off x
{
    int u=x;
    if (q2[x].sz()>=2) ans._pop(q2[x].get_two());
    q2[x]._push(0);
    if (q2[x].sz()>=2) ans._push(q2[x].get_two());
    while (f[u])
    {

        if (q2[f[u]].sz()>=2) ans._pop(q2[f[u]].get_two());
        if (q1[u].sz()) q2[f[u]]._pop(q1[u]._top());
        q1[u]._push(ds(f[u],x));
        q2[f[u]]._push(q1[u]._top());
        if (q2[f[u]].sz()>=2) ans._push(q2[f[u]].get_two());
        u=f[u];
    }
}

int cal2(int x)//turn_on x
{
    int u=x;
    if (q2[x].sz()>=2) ans._pop(q2[x].get_two());
    q2[x]._pop(0);
    if (q2[x].sz()>=2) ans._push(q2[x].get_two());
    while (f[u])
    {
        if (q2[f[u]].sz()>=2) ans._pop(q2[f[u]].get_two());
        q2[f[u]]._pop(q1[u]._top());
        q1[u]._pop(ds(f[u],x));
        if (q1[u].sz()) q2[f[u]]._push(q1[u]._top());
        if (q2[f[u]].sz()>=2) ans._push(q2[f[u]].get_two());
        u=f[u];
    }
}

void get_rot(int x,int fa)
{
    sz[x]=1;g[x]=0;
    for (int i=head[x];i;i=b[i].next)
    {
        int v=b[i].v;
        if (v==fa||vis[v]) continue;
        get_rot(v,x);
        sz[x]+=sz[v];
        g[x]=max(g[x],sz[v]);
    }
    g[x]=max(g[x],now_sz-sz[x]);
    rot=g[x]<g[rot]?x:rot;
}

void build(int x)
{
    vis[x]=1;
    for (int i=head[x];i;i=b[i].next)
    {
        int v=b[i].v;
        if (vis[v]) continue;
        rot=0;now_sz=sz[v];
        get_rot(v,0);
        f[rot]=x;
        build(rot);
    }
}

void dfs(int x,int fa)
{
    for (int i=head[x];i;i=b[i].next)
    {
        int v=b[i].v;
        if (v==fa) continue;
        dep[v]=dep[x]+1;
        anc[v][0]=x;
        dfs(v,x);
    }
}

int main()
{

    read(n);
    for ( i=1;i<n;++i) 
      read(x),read(y),add(x,y),add(y,x);
    now_sz=n,rot=0,get_rot(1,0),dep[rot]=1,dfs(rot,0),build(rot);
    for ( j=1;j<17;++j)
     for ( i=1;i<=n;++i) 
      anc[i][j]=anc[anc[i][j-1]][j-1];
    for ( i=1;i<=n;++i) cal(i);
    read(T);
    off_tot=n;
    while (T--)
        scanf("%s",s),s[0]=='G'?printf("%d\n",off_tot<=1?off_tot-1:ans._top()):
        (((read(x)),a[x]=a[x]==1?0:1)?(--off_tot,cal2(x)):(++off_tot,cal(x)));
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值