[bzoj4644]经典傻逼题

话说这道题是因为ditoly大佬无聊时候想做sb题搜索了一下"傻逼题"搜到的,刚好今天学习了线性基,在ditoly大佬的帮助下做完啦。

------------------------------------------------------------------------------

题意:定义割操作是对于原图的一个点集,所有恰好只有一个点在集合中的边的集合,它的权值是所有边的异或和。

给定n个点,m个操作,每次向其中两个点中添加一条边,然后求一个最大的割的权值。n<=500 m<=1000  权值的二进制长度L<=1000

题解:首先很容易发现,我们把每个点的权值设成所有它在的边的权值异或和,原题转换为求一个最大异或和的点集,最大异或和我们考虑用线性基求出。

但是线性基不支持删除操作,我们考虑避免掉删除操作,具体实现就是采用线段树分治,对询问建一个时间轴就好啦。每次插入操作是L^2的,总复杂度mL^2logn

#include<iostream>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<vector>
#define ML 1000
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < ‘0‘ || ch > ‘9‘){ if(ch == ‘-‘) f = -1;  ch = getchar();}
    while(ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}

int n,m,last[505];
struct node{int l,r;vector<bitset<1002> >s;vector<int>p;}T[4005];
bitset<1002> s[4005],now;
char st[1005];

void build(int x,int l,int r)
{
    if((T[x].l=l)==(T[x].r=r))return;
    int mid=l+r>>1;
    build(x<<1,l,mid);build(x<<1|1,mid+1,r);
}

void ins(int x,int l,int r,bitset<1002>&b)
{
//    cout<<"ins"<<x<<" "<<l<<" "<<r<<endl;
    if(T[x].l==l&&T[x].r==r){T[x].s.push_back(b);return;}
    int mid=(T[x].l+T[x].r)>>1;
    if(r<=mid) ins(x<<1,l,r,b);
    else if(l>mid) ins(x<<1|1,l,r,b);
    else {ins(x<<1,l,mid,b);ins(x<<1|1,mid+1,r,b);}
}

void dfs(int x)
{
//    cout<<"dfs"<<x<<endl;
    for(int i=0;i<T[x].s.size();i++)
        for(int j=1;j<=ML;j++) if(T[x].s[i][j])
            if(!s[j][j]){s[j]=T[x].s[i];T[x].p.push_back(j);break;}
            else T[x].s[i]^=s[j];
    if(T[x].l!=T[x].r) dfs(x<<1),dfs(x<<1|1);
    else
    {
        now.reset();
        for(int i=1;i<=ML;i++) if(s[i][i]&&!now[i]) now^=s[i];
        int j=1;for(;j<=ML&&!now[j];j++);if(j>ML) printf("0");
        else for(;j<=ML;j++) printf("%d",now[j]?1:0);
        puts("");
    }
    for(int i=0;i<T[x].p.size();i++)
        s[T[x].p[i]].reset();
}

int main()
{
    read();n=read();m=read();
    build(1,1,m);
    for(int i=1;i<=m;i++)
    {
         int u=read(),v=read();
         scanf("%s",st+1);if(u==v) continue;
         int len=strlen(st+1);now.reset();
         for(int j=1;j<=len;j++)
             now[ML-len+j]=st[j]==‘1‘?1:0;
         if(last[u])ins(1,last[u],i-1,s[u]);last[u]=i;
         if(last[v])ins(1,last[v],i-1,s[v]);last[v]=i;
         s[u]^=now;s[v]^=now;
    }
    for(int i=1;i<=n;i++)if(last[i]<=m&&last[i]) ins(1,last[i],m,s[i]);
    for(int i=1;i<=n;i++)s[i].reset();
    dfs(1);
    return 0;
}
时间: 2024-12-04 10:55:21

[bzoj4644]经典傻逼题的相关文章

经典傻逼题

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

BZOJ 2222: [Cqoi2006]猜数游戏【神奇的做法,傻逼题,猜结论】

2222: [Cqoi2006]猜数游戏 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 604  Solved: 260[Submit][Status][Discuss] Description 佳佳和明明玩一个猜数游戏.佳佳想一个1~n之间的整数,明明每次可以随便猜一个数.从第二次猜测起,佳佳告诉明明本次猜测的数和上次猜测的数相比哪个更接近.B表示本次猜测的数更接近,W表示上次猜测的数更接近.如果两次猜测的接近程度一样,则既可回答B也可回答W.

CDOJ 486 Good Morning 傻逼题

Good Morning Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/486 Description Sam loves Lily very much that he shows his love to her through all kinds of ways. This morning, Lily received an e-mail from Sam. Lily kn

Car 的旅行路线——又是傻逼和傻逼题纠缠的故事

洛谷和CodeVS 版本应该是一样的,有多组数据并且要求保留一位小数.Vijos 的版本没有多组数据,要保留两位小数.胡搅蛮缠换了两次最短路算法,终于还是做出来了. 1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<vector> 7 #include<c

cdoj 93 King&#39;s Sanctuary 傻逼几何题

King's Sanctuary Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/93 Description The king found his adherents were building four sanctuaries for him. He is interested about the positions of the sanctuaries and want

【复习】深夜复习傻逼图论的玩意

不写点东西明天要挂啊 不想看傻逼的直接跳到后面   0.存储结构(你妈写这个凑字数呀 邻接表&插入边 struct edge{ int to,next,v; }e[M]; int cnt,last[N]; void insert(int a,int b,int c){ e[++cnt]=(edge){b,last[a],c};last[a]=cnt; } void link(int a,int b,int c){ insert(a,b,c);insert(b,a,c); } 1.闭着眼睛摸了个s

eclipse真是最纯粹的傻逼。

eclipse真是最纯粹的傻逼.... 重要的事情说三遍. 从我开始用eclipse开始,各种版本,从C/C++版本到JAVA版本,从linux版本到Windows版本,遇到无数bug,这不知道为何有一帮脑子吃屎的人吹嘘这货好用(傻逼遇傻逼). 这货就是纯粹傻逼写的给傻逼用的. 典型bug诸如代码莫名报错,clean都不行,refresh后却一切正常. 工程用的用的就打不开了 makefile文件不更新导致编译出错. 新建文件finsh后毫无反应(没有文件产生)…… 创建工程finish没反应,

记录自己的傻逼的错误:找不到或无法加载主类

记录自己的傻逼错误 自己用eclipse写的java代码,突然想在黑窗口看一下垃圾回收的日志,发现总是提示"错误:找不到或无法加载主类"这个错误,以前每天写代码都是好的,用eclipse运行也一直是好的,怎么今天在黑窗口就不行了呢,百度了下,说是JDK的环境配置有问题,然后我就仔细的检查了好几遍,依然无法解决,百度上面普遍这个问题的答案都是JDK的环境没有配置好,没有其他的,然后我就自己在Notepad++上面写一个小程序,发现可以运行也,为什么不能运行eclipse写出来的代码呢??

我是个很牛逼地活在别人眼里的傻逼

| 忏悔录 | 现在的我 沉心静气,尝试专一 曾经的我 自卑自负,大落大起 生活教会我沉稳与内敛 而背后的老师 是不堪回首的自己 我不会避讳什么,或使用小A.B兄一类的笔名自欺欺人,这就是我的故事,也许,也是众多和我一样自卑与自负一体,但已开始悔悟的朋友们的故事--这篇文章,除了自省,还想给有像我一样经历得同仁说一句:乖,醒一醒.--Emerson 1401354763 偶然看到一篇名为<我曾是个很牛逼地活在别人眼里的傻逼>的微信.冲着标题进去,想看看这位到底是怎么牛逼又怎么傻逼.看完,懵逼-