您的位置:首页 > 其它

ACM bitset模板 Gym 100345H

2015-08-29 21:46 351 查看
bitset模板

bitset可以看作bool数组,但优化了空间复杂度和时间复杂度,并且可以像整形一样按位与或。

优化作用:

常常碰到处理的数组只有0和1的变化,此时就可以使用bitset优化。比如求两个集合的交集可以使用按位与运算,求并集可以使用按位或运算

#include<bitset>
biset<32> s(10);  //32位的bitset,赋值为十进制的10
bitset<32> bs("011010101001"); //用字符串初始化
bs[20]=1; //像数值一样对某一位进行操作

s=10; //赋值为十进制的10
s.reset();//清零
s.set(); //全部位置放置为1
s.count(); //统计1的个数

b.flip(); //把b中所有二进制位逐位取反
b.to_ulong();//用b中同样的二进制位返回一个unsigned long值


b1 = b2 ^ b3;//按位异或
b1 = ~b2;//按位补
b1 = b2 << 3;//移位


参考:

ACM的奇计淫巧_bitset优化

C++ bitset类的使用与简介

bitset - C++ Reference

例题:

Gym 100345H

这是一个有向无环图,可以有拓扑序列

bitset<maxn> f[maxn]; // f[i]保存i的到达信息,其中f[i][j]表示i是否可以到达j

对于任意与i相连的点j,f[i]=f[i]|f[j],f[i][j]=1,更新信息,具体dfs实现,bitset实现压位

修改操作只有1000次,每一次重新建图即可,O(1000*n^2)

查询为O(1)

/*
 * Author: NICK WONG
 * Created Time:  2015/8/29 15:41:21
 * File Name: h.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=210;
const long long maxint=-1u>>1;
const long long maxlong=maxint*maxint;
typedef long long lint;
int n,m,k;
bool a[maxn][maxn],vis[maxn];
bitset<maxn> f[maxn];

void init()
{
    memset(a,0,sizeof(a));
    for (int i=1; i<=m; i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        a[u][v]=true;
    }
}

void dfs(int x)
{
    if (vis[x]) return;
    vis[x]=true;
    for (int i=1; i<=n; i++)
        if (a[x][i])
        {
            dfs(i);
            f[x]|=f[i];//bitset
            f[x][i]=1;   
        }
}

void build()
{
    memset(vis,0,sizeof(vis));
    for (int i=1; i<=n; i++) f[i].reset();
    for (int i=1; i<=n; i++)
        if (!vis[i]) dfs(i);
    int sum=0;
    for (int i=1; i<=n; i++)
        sum+=f[i].count();
    //for (int i=1; i<=n; i++)
        //for (int j=i+1; j<=n; j++)
            //if (f[i][j]) 
            //{
                //sum++;
            //}
    printf("%d\n",sum);
}

void work()
{
    build();
    scanf("%d",&k); getchar();
    for (int i=1; i<=k; i++)
    {
        char c,ha;
        int u,v;
        scanf("%c%d%d%c",&c,&u,&v,&ha);
        if (c=='?')
        {
            if (f[u][v]) puts("YES"); else puts("NO");
        } else if (c=='+')
        {
            a[u][v]=true;   
            build();
        } else if (c=='-')
        {
            a[u][v]=false;
            build();
        }
    }   
}

int main()
{
    freopen("settling.in", "r", stdin);
    freopen("settling.out", "w", stdout);
    while(cin>>n>>m)
    {
        init();
        work();
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}


Problem H. Settling the Universe Up

Input file:

settling.in

Output file:

settling.out

Time limit: 2 seconds

Memory limit: 256 megabytes

The
colonists from Earth are settling the Universe up. More and more young families choose to leave

the Earth for good in order to bring the human race to the new heights. Well, actually they just have

no way back because hypertunnels that are used for the colonization are one-way.

You work in the coordination center of the colonization. There are

n planets that are used in the

process of colonization, numbered from 1 to

n. Earth has number 1. Brave pathfinders sometimes put

a hypertunnel from one planet to another. The planets are numbered in order of decreasing of their

torsion power, so a hypertunnel can only exist from a planet with smaller number to a planet with

greater number. Sometimes, due to torsion fields distortion, hypertunnels disappear. Your task is to

trace all such events, quickly answer questions whether there exists a path from one planet to another,

and provide some other statistics.

After some period of working with pen and paper you decide to write a program to do the work for you.

Input

The first line of the input file contains

n — the number of planets (1

≤ n

200), and

m — the number

of hypertunnels that exist at the moment you start writing the program. The following

m lines describe

hypertunnels, each hypertunnel is described by two integer numbers:

u and

v — the planet where the

tunnel starts and the planet where the tunnel goes (1

≤ u < v

n).

The next line contains

k — the number of events and queries (1

≤ k

100000, the number of events

doesn’t exceed 1000). The following

k lines contain information about events and queries. Each event

is either “+

i j” if the hypertunnel between

i and

j is added, or “-

i j” if the hypertunnel between

i

and

j has disappeared. No tunnel is created if there is a tunnel already, a tunnel can disappear only if

it exists. Each query is “?

i j” and asks whether there is a path from planet

i to planet

j. In all events

and queries

i < j.

Output

Output

k+1 lines. The first line must contain the number of pairs of planets (u,
v) such that it is possible

to get from planet

u to planet

v by hypertunnels that initially exist. After each event output the updated

number of pairs. After each query output “YES”
or “NO”.

Example

settling.in

4 4

1 2

2 4

1 3

3 4

6

? 2 3

+ 2 3

- 1 3

- 1 2

+ 1 4

? 2 3

settling.outsettling.out

settling.out5

NO

6

6

3

4

YES
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: