• bzoj4419[SHOI2013]发微博


    题意:给你一个初始没有边,点权均为0的无向图,三种操作:加边,删边,选择一个点将当前与之相邻的点(不包括自身)的点权+1,询问最后所有点的点权。

    据说正解是set维护每个人的朋友,然后考虑每次加边、删边对答案的贡献......但作为脑子有坑的选手,我搞出了一个动态开点线段树....首先离线,分别考虑每条边对答案的贡献。不妨分别考虑这条边存在的每一个时间区间。那么我们只要知道这个时间区间中两个端点各进行了几次点权增加(发微博)操作就可以更新两边的答案。考虑对每一个点开一棵线段树,如果这个点在第i个操作中发了一条微博就把下标为i处+1,查询的时候线段树区间查询即可。直接建的空间复杂度n*mlogm会TLE+MLE,所以动态开点,每次修改操作建一条链,总的空间复杂度mlogm。用map存了一下边所以很慢明明是线段树常数炸天

    注意m次操作后没有被删除的边也要更新答案,WA了一发。

    #include<cstdio>
    #include<map>
    using namespace std; 
    const int maxn=200005,maxm=500005;
    int n,m;
    struct node{
        int sum;
        node *lch,*rch;
        node(){
            sum=0;
            lch=rch=0;
        }
    }t[maxm*20];int cnt=0;
    node *root[maxn];
    map<long long,int> dict;
    void Insert(node *&rt,int k,int l,int r){
        if(rt==0){
            ++cnt;rt=t+cnt;
        }
        if(l==r){
            rt->sum++;
            return;
        }
        int mid=(l+r)>>1;
        if(k<=mid)Insert(rt->lch,k,l,mid);
        else Insert(rt->rch,k,mid+1,r); 
        rt->sum=0;
        if(rt->lch)rt->sum+=rt->lch->sum;
        if(rt->rch)rt->sum+=rt->rch->sum;
    }
    int ql,qr,ans;
    void query(node *rt,int l,int r){
        if(rt==0)return;
        if(ql<=l&&r<=qr){
            ans+=rt->sum;
            return;
        }
        int mid=(l+r)>>1;
        if(ql<=mid)query(rt->lch,l,mid);
        if(qr>mid)query(rt->rch,mid+1,r);
    }
    int u[maxm],v[maxm],from[maxm],to[maxm];int tot=0;
    int res[maxn];
    int main(){
        scanf("%d%d",&n,&m);
        char buf[2];
        int a,b;
        for(int i=1;i<=m;++i){
            scanf("%s",buf);
            if(buf[0]=='!'){
                scanf("%d",&a);
                Insert(root[a],i,1,m);
            }else if(buf[0]=='+'){
                scanf("%d%d",&a,&b);
                if(a>b)swap(a,b);
                dict[(a-1)*1LL*n+b]=i;
            }else{
                scanf("%d%d",&a,&b);
                if(a>b)swap(a,b); 
                ++tot;
                u[tot]=a;v[tot]=b;
                from[tot]=dict[(a-1)*1LL*n+b];
                dict.erase((a-1)*1LL*n+b);
                to[tot]=i;
            }
        }
        for(int i=1;i<=tot;++i){
            ql=from[i];qr=to[i];
            ans=0;
            query(root[v[i]],1,m);res[u[i]]+=ans;
            ans=0;
            query(root[u[i]],1,m);res[v[i]]+=ans;
        }
        for(map<long long,int>::iterator pt=dict.begin();pt!=dict.end();++pt){
            ql=pt->second;qr=m; 
            a=(pt->first-1)/n+1;b=(pt->first)%n;
            if(b==0)b=n;
            ans=0;
            query(root[a],1,m);res[b]+=ans;
            ans=0;
            query(root[b],1,m);res[a]+=ans;
        } 
        for(int i=1;i<=n;++i)printf("%d%c",res[i],(i==n)?'
    ':' ');
    }
  • 相关阅读:
    MATLAB远程桌面打开失败解决办法
    Windows 10 激活步骤
    Windows 10 重装技巧
    Office2019部署代码
    vi命令行命令的积累
    github项目cim(命令行即时通讯), HashedWheelTimer学习笔记
    java读取资源文件/打jar包后读取资源文件的区别
    vmware虚拟机网络配置(物理机能用ssh连接虚拟机, 虚拟机能共享物理机网卡上外网)仅主机模式,nat模式应该也可以
    spring cloud 组件学习 hystrix学习
    netty优化学习积累+++++++
  • 原文地址:https://www.cnblogs.com/liu-runda/p/6009323.html
Copyright © 2020-2023  润新知