• bzoj4644: 经典傻逼题


    我是弟弟。。。左左睿的神题还是另外一题的真子集

    首先令点权为和它相连的边权异或和,容易发现一个点集的割就是点权和

    但是m次线性基肯定是不行的

    学了个新东西,线段树分治

    首先他的下标是时间

    对于一个点,他的权值反映在时间轴上就是多段权值

    然后插入到线段树上,容易证明如果是一段相同的权值,最多会被拆成logn段

    对于每一段直接在管理节点上面开个vector记录,相当于这是他的子节点共用的

    最后遍历整棵树,到达一个点就把它上面的插进线性基,回溯就清空

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<bitset>
    #include<vector>
    using namespace std;
    
    struct node
    {
        int l,r,lc,rc;
        vector< bitset<1100> >s;
        vector<int>clear;
    }tr[4100];int trlen,last[510];
    void bt(int l,int r)
    {
        int now=++trlen;
        tr[now].l=l;tr[now].r=r;
        tr[now].lc=tr[now].rc=-1;
        if(l<r)
        {
            int mid=(l+r)/2;
            tr[now].lc=trlen+1;bt(l,mid);
            tr[now].rc=trlen+1;bt(mid+1,r);
        }
    }
    bitset<1100>lt[1100],t;
    void insert(int now,int l,int r,int p)
    {
        if(tr[now].l==l&&tr[now].r==r)
        {
            tr[now].s.push_back(lt[p]); 
            return ;
        }
        
        int lc=tr[now].lc,rc=tr[now].rc;
        int mid=(tr[now].l+tr[now].r)/2;
        
             if(r<=mid)  insert(lc,l,r,p);
        else if(mid+1<=l)insert(rc,l,r,p);
        else insert(lc,l,mid,p),insert(rc,mid+1,r,p);
    }
    
    void add(int now,int o)//线性基 
    {
        for(int i=1;i<=1000;i++)
            if(tr[now].s[o][i])
            {
                if(!lt[i][i])
                {
                    lt[i]=tr[now].s[o];
                    tr[now].clear.push_back(i);
                    break;
                }
                else tr[now].s[o]^=lt[i];
            }
    }
    void getmax()
    {
        t.reset();
        for(int i=1;i<=1000;i++) 
            if(!t[i])t^=lt[i];
        bool flag=false;
        for(int i=1;i<=1000;i++)
        {
            if(t[i]==1)flag=true;
            if(t[i]|flag)
                printf("%d",(t[i]==1));
        }
        if(flag==false)printf("0");
        printf("
    ");
    }
    void dfs(int now)
    {
        for(int i=0;i<tr[now].s.size();i++)add(now,i);
        
        if(tr[now].l==tr[now].r)getmax();
        else dfs(tr[now].lc),dfs(tr[now].rc);
        
        for(int i=0;i<tr[now].clear.size();i++)lt[tr[now].clear[i]].reset();
    }
    
    char ss[1100];int sslen;
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int ID,n,m,x,y;
        scanf("%d%d%d",&ID,&n,&m);
        trlen=0;bt(1,m);
        memset(last,0,sizeof(last));
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%s",&x,&y,ss+1);sslen=strlen(ss+1);
            if(x==y)continue;
            t.reset();
            for(int j=1;j<=sslen;j++)
                t[1000-sslen+j]=(ss[j]=='1');
            
            if(last[x]!=0)insert(1,last[x],i-1,x); last[x]=i;
            if(last[y]!=0)insert(1,last[y],i-1,y); last[y]=i;
            lt[x]^=t;
            lt[y]^=t;
        }
        for(int i=1;i<=n;i++)
            if(last[i]!=0&&last[i]<=m)insert(1,last[i],m,i);
                
        for(int i=1;i<=n;i++)lt[i].reset();
        dfs(1);
        
        return 0;
    }
  • 相关阅读:
    Redis3.0.1 Stable版本的集群部署(Mac)
    Maven的包依赖冲突可引发java.lang.IncompatibleClassChangeError错误
    Key/Value存储系统etcd的特性
    实时消息平台NSQ的特性
    StringIO函数
    对文件内容进行迭代
    基本文件方法
    打开文件
    正则表达式知识点汇总
    编译
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10196492.html
Copyright © 2020-2023  润新知