首页 > 其他分享 >bitset小专题(待续)

bitset小专题(待续)

时间:2023-02-01 22:22:49浏览次数:53  
标签:待续 typedef 专题 int 路径 long bitset define

bitset:一个01位如果用bool存的话需要 1byte,而用bitset只需要 1bit(=1/8 byte)
每次两个集合取并的时候可以除以一个大常数(32/64),从而优化复杂度

LOJ515
设 \(dp[i]\) 表示考虑到第 \(i\) 个区间,能形成的和的状态是0/1(该位为1代表可以出现这个数,否则不能)
转移就枚举一下当前区间 or 一下即可
注意这里不能用 1<<i 这种写法,因为会爆int

// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back

using namespace std;

typedef long long ll;
typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 105;

int n;
int a[maxn], b[maxn];
bitset<101 * 101 * 101>dp[2];

signed main() {
    ios::sync_with_stdio(false);
    cin >> n;

    for (int i = 1; i <= n; i++)
        cin >> a[i] >> b[i];

    for (int i = 1; i <= n; i++) {
        dp[i & 1].reset();

        for (int j = a[i]; j <= b[i]; j++) {
            dp[i & 1] |= (dp[i & 1 ^ 1] << (j * j));
        }

        if (i == 1)
            for (int j = a[i]; j <= b[i]; j++)
                dp[i & 1][j * j] = 1;
    }

    cout << dp[n & 1].count();

    return 0;
}

abc287_ex
帮助理解floyd本质的好题
floyd的代码一般是这样:

for(int k=1;k<=n;k++){
  for(int i=1;i<=n;i++){
    for(int j=1;j<=n;j++){
      dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
    }   
  }
}

这里 \(k\) 的深层含义就是:\(i\rightarrow j\) 的路径上,(去除了起点终点)路径上的点的编号均不超过 \(k\) 时的最短距离
每次 \(k+1\) 的时候,就相当于 \((i,j)\) 的路径上可以出现 \(k+1\) 这个点,因此用 \(dis[i][k']+dis[k'][j]\) 更新之
这个题实际上就考察了floyd的本质。每次枚举一下路径上的最大点 \(k\),然后传递闭包即可
又因为我们只需要记录是否(路径上只利用 \(1..k\) 的点)可达即可,因此可以用bitset优化一下,时间复杂度 \(O(\frac{n^3+nQ}{32})\)

// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back

using namespace std;

typedef long long ll;
typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f;

int n,m;
bitset<2005>acc[2005];
int s[10005], t[10005], ans[10005];
signed main(){
	memset(ans,-1,sizeof ans);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int x,y;scanf("%d%d",&x,&y);
		acc[x][y] = 1;
	}
	int Q;
	scanf("%d",&Q);
	for(int i=1;i<=Q;i++){
		scanf("%d%d",&s[i],&t[i]);
	}
	for(int k=1;k<=n;k++){
		acc[k][k] = 1;
		for(int i=1;i<=n;i++){
			if(acc[i][k])acc[i] |= acc[k];
		}
		for(int i=1;i<=Q;i++){
			int u=s[i], v=t[i];
			if(u<=k && v<=k && acc[u][v] && ans[i]==-1){
				ans[i] = k;
			}
		}
	}
	for(int i=1;i<=Q;i++)printf("%d\n",ans[i]);
	
	return 0;
}

标签:待续,typedef,专题,int,路径,long,bitset,define
From: https://www.cnblogs.com/SkyRainWind/p/17084297.html

相关文章