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;
}
经典傻逼题
原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14559385.html