zoukankan      html  css  js  c++  java
  • 「LibreOJ β Round #7」小埋与游乐场

    一、题目

    点此看题

    二、解法

    首先思考这题怎么修改,因为有用的位只有 ( t lowbit),我们会把 ( t lowbit) 小的 (b) 异或上 ( t lowbit) 大的 (a) 达到让总和减少的目的,明白这一点之后就可以做没有元素同时在 (A,B) 中出现这个部分分了。

    特殊情况是 (a=b) 可以减少的量是 (lowbit(a)),你可能会想讨论但这东西影响确实太大了,难做。

    换个思路,考虑现在问题的本质其实是一个带权匹配模型,而且只有两种边:(a=b) 减少 (lowbit(a))(lowbit(a)>lowbit(b)) 减少 (lowbit(a)-lowbit(b))

    不知道你发现了吗,本题的边权值只和 (lowbit(x)) 有关,而只有 (30) 种不同的 (lowbit),这启示我们可以按 (lowbit) 划分等价类,还是原来费用流的图,我们把容量修改一下就可以随便跑了。

    三、总结

    划分等价类真是重要的思想,原来它不只可以应用到 (dp) 上。我觉得它的本质是观察代价和什么量有关,然后找变量之间的平行关系,能达到优化复杂度的目的。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <map>
    using namespace std;
    const int M = 1200005;
    const int N = 105;
    const int inf = 0x3f3f3f3f;
    #define ll long long
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,m,k,ca[N],cb[N],cc[N];ll dis[N],ans;
    int tot,S,T,f[N],pre[N],lst[N],flow[N],in[N];
    map<int,int> mp1,mp2;
    struct edge
    {
    	int v,c,f,next;
    }e[N*N];
    void add(int u,int v,int c,int fl)
    {
    	e[++tot]=edge{v,c,fl,f[u]},f[u]=tot;
    	e[++tot]=edge{u,-c,0,f[v]},f[v]=tot;
    }
    int bfs()
    {
    	queue<int> q;
    	for(int i=0;i<=T;i++) dis[i]=-1e18;
    	flow[S]=inf;pre[S]=lst[S]=dis[S]=0;
    	q.push(S);in[S]=1;
    	while(!q.empty())
    	{
    		int u=q.front();q.pop();in[u]=0;
    		for(int i=f[u];i;i=e[i].next)
    		{
    			int v=e[i].v,c=e[i].c;
    			if(dis[v]<dis[u]+c && e[i].f>0)
    			{
    				dis[v]=dis[u]+c;
    				lst[v]=i;pre[v]=u;
    				flow[v]=min(e[i].f,flow[u]);
    				if(!in[v]) q.push(v),in[v]=1;
    			}
    		}
    	}
    	return flow[T]>0;
    }
    void EK()
    {
    	while(bfs() && k)
    	{
    		if(dis[T]<=0) break;
    		int t=min(k,flow[T]);
    		ans-=dis[T]*t;
    		k-=t;
    		int zy=T;
    		while(zy!=S)
    		{
    			e[lst[zy]].f-=flow[T];
    			e[lst[zy]^1].f+=flow[T];
    			zy=pre[zy];
    		}
    	}
    	printf("%lld
    ",ans);
    }
    int lowbit(int x) {return x&(-x);}
    int id(int x) {return (int)log2(lowbit(x));}
    int main()
    {
    	n=read();tot=1;
    	for(int i=1;i<=n;i++)
    	{
    		int x=read();
    		if(x==0) continue;
    		ca[id(x)]++;
    		ans+=lowbit(x);
    		mp2[x]++;
    	}
    	m=read();S=70;T=71;
    	for(int i=1;i<=m;i++)
    	{
    		int x=read();
    		if(x==0) continue;
    		cb[id(x)]++;
    		mp1[x]++;
    	}
    	k=read();
    	for(auto x:mp1)
    		cc[id(x.first)]+=min(x.second,mp2[x.first]);
    	for(int i=0;i<32;i++)
    	{
    		add(S,i,0,ca[i]);
    		add(i+32,T,0,cb[i]);
    		for(int j=0;j<i;j++)
    			add(i,j+32,(1<<i)-(1<<j),inf);
    		add(i,i+32,1<<i,cc[i]);
    	}
    	EK();
    }
    
  • 相关阅读:
    ubuntu16.04本地软件源搭建
    2080TI显卡ubuntu16.04机器学习安装和克隆
    PLSQL导入excel数据方法
    只有英伟达显卡输出口的电脑安装ubuntu系统记录
    百度人脸识别学习
    http application/x-www-form-urlencoded 模式响应学习
    JS中继承的几种实现方式
    浅拷贝和深拷贝
    防抖和节流
    HTML知识点总结
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15226591.html
Copyright © 2011-2022 走看看