• BZOJ4644 经典傻逼题


    Description

    这是一道经典傻逼题,对经典题很熟悉的人也不要激动,希望大家不要傻逼。
    考虑一张$N$个点的带权无向图,点的编号为$1$到$N$。 对于图中的任意一个点集(可以为空或者全集),所有恰好有一个端点在这个点集中的边组成的集合被称为割。 一个割的权值被定义为所有在这个割上的边的异或和。一开始这张图是空图, 现在,考虑给这张无向图不断的加边, 加入每条边之后,你都要求出当前权值最大的割的权值, 注意加入的边永远都不会消失。

    Solution

    如果把点的权值定义为与这个点相连的边的权值的异或,一个点集的割的权值就是这些点的权值的异或

    于是问题变成最大异或和

    建一棵以时间为下标的线段树,对于每一个点在某个时间段内的权值在线段树上修改

    最终计算答案时在线段树上DFS

    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<bitset>
    using namespace std;
    int n,m,tag[505];
    char s[1005];
    vector<bitset<1005>>ve[4005];
    vector<int>bin[4005];
    bitset<1005>las[1005],temp;
    inline int read(){
        int f=1,w=0;
        char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return f*w;
    }
    void update(int i,int l,int r,int L,int R,int p){
        if(L<=l&&r<=R){ve[i].push_back(las[p]);return;}
        int mid=l+r>>1;
        if(L<=mid)update(i<<1,l,mid,L,R,p);
        if(R>mid)update(i<<1|1,mid+1,r,L,R,p);
    }
    void insert(int x,int y){
        for(int i=1;i<=1000;i++)if(ve[x][y][i])
            if(!las[i][i]){las[i]=ve[x][y],bin[x].push_back(i);break;}
            else ve[x][y]^=las[i];
    }
    void query(){
        temp.reset();
        for(int i=1;i<=1000;i++)if(!temp[i])temp^=las[i];
        int i=1;
        for(;i<=1000&&!temp[i];i++);
        if(i==1001)puts("0");
        else{
            for(;i<=1000;i++)printf("%d",(temp[i]==1));
            putchar(10);
        }
    }
    void dfs(int i,int l,int r){
        for(int j=0;j<ve[i].size();j++)insert(i,j);
        if(l==r)query();
        else{
            int mid=l+r>>1;
            dfs(i<<1,l,mid),dfs(i<<1|1,mid+1,r);
        }
        for(int j=0;j<bin[i].size();j++)las[bin[i][j]].reset();
    }
    int main(){
        read(),n=read(),m=read();
        for(int i=1;i<=m;i++){
            int x=read(),y=read(),len;
            scanf("%s",s+1),len=strlen(s+1),temp.reset();
            if(x==y)continue;
            for(int j=1;j<=len;j++)temp[1000-len+j]=s[j]-'0';
            if(tag[x])update(1,1,m,tag[x],i-1,x);
            if(tag[y])update(1,1,m,tag[y],i-1,y);
            tag[x]=tag[y]=i,las[x]^=temp,las[y]^=temp;
        }
        for(int i=1;i<=n;i++)if(tag[i]<=m&&tag[i])update(1,1,m,tag[i],m,i),las[i].reset();
        dfs(1,1,m);
        return 0;
    }
    经典傻逼题
  • 相关阅读:
    把Asp.net Core程序代码部署到Ubuntu(不含数据库)
    2019周笔记(3.11-3.16)
    利用StackExchange.Redis和Log4Net构建日志队列
    Windows环境下安装配置Mosquitto服务及入门操作介绍
    2019周笔记(2.25-3.01)(压缩数据库)
    2019周笔记(2.18-2.23)
    WinForm客户端限速下载(C#限速下载)
    2019周笔记(2.14-2.17)(聚集索引、非聚集索引)
    高并发场景下秒杀项目静态锁的使用疑问
    线性结构队列以及应用(上)
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14559385.html
Copyright © 2020-2023  润新知