【BZOJ-3578】GTY的人类基因组计划2 set + map + Hash 乱搞

3578: GTY的人类基因组计划2

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 367  Solved: 159
[Submit][Status][Discuss]

Description

GTY召唤了n个人来做实验,GTY家的房子很大,有m个房间一开始所有人都在1号房间里,GTY会命令某人去某个房间等待做实验,或者命令一段区间的房间开始实验,实验会获得一些实验信息点数,点数为房间里的人数,如果一个房间里的一群人已经做过实验了那么这些人将不会增加实验信息点数(不会增加是针对这一群人的,不是对这群人中的每个人,即1,2,3做了实验,1,2再做实验还会增加2点实验点数)

Input

第一行两个整数n,m,q(n,m,q<=10^5)表示人数,房间数和操作数
接下来q行每行一个操作 "C i j"表示让第i个人去房间j "W l r" 表示让区间[l,r]的房间做实验

Output

对于每一个W操作,输出一个数,表示此次操作所获得的实验点数

Sample Input

3 5 7
C 1 2
C 2 2
W 1 2
C 3 2
W 1 2
C 3 3
W 1 3

Sample Output

3
3
0

HINT

善用STL

Source

By orzpzmaimeng

Solution

这道题是亲学长zky出的,学长本人有多种做法:传送门

这里采用的是DavidLee1999课件中的方法,利用STL乱搞

首先,我们用set去维护可以计入答案的房间,

所以同时会涉及如何对集合Hash,一个神奇的方法:对每个数rand出来一个longlong,对于集合Hash值,就是对于集合中每个数计算异或和

(这里之所以rand出longlong,考虑生日悖论所导致的冲突)

那么这里还需要记录几个量:每个房间的人数,每个人所在的房间号,再利用map去记录每个集合是否用过

那么对于一次移动,我们删去两个房间,并且最多加入两个新房间,所以其本质上有用的房间数是O(Q)级的

那么每次询问,我们把set中的房间取出统计答案,再标记为已用,并删掉就好了

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<set>
#include<map>
using namespace std;
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,Q;
#define MAXN 100010
#define MAXM 100010
long long id[MAXN],room[MAXM];
int num[MAXM],pos[MAXN];
map<long long,bool>mp;
set<int>st;
set<int>::iterator ist;
long long GetHash() {return (((long long)rand()<<16) | rand());}
void Change(int x,int y)
{
    if (pos[x]==y) return;
    st.erase(pos[x]); st.erase(y);
    room[pos[x]]^=id[x]; num[pos[x]]--;
    if (!mp[room[pos[x]]]) st.insert(pos[x]);
    pos[x]=y; room[y]^=id[x]; num[y]++;
    if (!mp[room[y]]) st.insert(y);
}
void Solve(int x,int y)
{
    int ans=0;
    for (ist=st.lower_bound(x); ist!=st.end() && *ist<=y; ist=st.lower_bound(x))
        mp[room[*ist]]=1,ans+=num[*ist],st.erase(ist);
    printf("%d\n",ans);
}
int main()
{
    srand(2000+1+4);
    N=read(),M=read(),Q=read();
    for (int i=1; i<=N; i++) id[i]=GetHash(),room[1]^=id[i],num[1]++,pos[i]=1;
    st.insert(1);
    while (Q--)
        {
            char opt[10]; scanf("%s",opt);
            int x=read(),y=read();
            switch (opt[0])
                {
                    case ‘C‘ : Change(x,y); break;
                    case ‘W‘ : Solve(x,y); break;
                }
        }
    return 0;
}

随机的话,比较稳妥的是srand(time(0)),但是BZOJ上会RE,那么据说采取妹子的生日会有特殊加成哦(我不会告诉你我用的妹子生日的)

时间: 2024-08-06 03:40:17

【BZOJ-3578】GTY的人类基因组计划2 set + map + Hash 乱搞的相关文章

BZOJ 3578 GTY的人类基因组计划2 set

题目大意:有一些人一开始都在一号房间.有一些指令使他们区别的房间.每次选定一段区间作试验,如果有的房间的组合已经做过试验,那么就不计入最后的试验点数,否则计入试验点数为试验的人数.问最后会获得多少试验点数. 思路:对于每一个人随即一个long long,一个集合所代表的数字就是这些long long的异或和.然后用set来暴力判重. CODE: #include <set> #include <cstdio> #include <cstring> #include &l

BZOJ3578 GTY的人类基因组计划2 HASH

题意:有N个人M个房间,初始时所有人都在1号房间,维护:1.让某个人去某个房间  2.假如[l,r]中所有的人还未一起统计过,Ans+=人数.输出Ans 题解: 集合HASH get 根据异或的性质,a^x^x=a,因此一个集合的HASH值就是其所有元素的异或起来的值 接下来就是STL大法好 将每个房间看成一个集合,每个人赋一个初始rand,set存储当前所有HASH值没有出现过的房间.对于每个询问,二分出所有区间之间的房间,统计答案即可. #include <set> #include &l

【分块】【哈希】bzoj3578 GTY的人类基因组计划2

每个房间用一个集合来维护,具体来说,就是给1-n的数每个数一个long long的hash值,往集合S里insert(i),就是S^=HASH[i]:erase(i),也是S^=HASH[i]. 用map/set维护某个集合是否已经做过实验. 分块,对每个块维护一个maxv[i],代表当前该块内的答案值,要注意,若某个房间的集合的vis[S[i]]==true,则它对其所在块没有贡献. 分块相对于线段树/平衡树/树套树的很大的好处,就是思路简单暴力,代码短,常数小,应对范围广,可以方便地扩张.

bzoj 3744: Gty的妹子序列 主席树+分块

3744: Gty的妹子序列 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 101  Solved: 34[Submit][Status] Description 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成了一个序列,每个妹子有一个美丽度. Bakser神犇与他打算研究一下这个妹子序列,于是Bakse

BZOJ 3744: Gty的妹子序列

3744: Gty的妹子序列 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1335  Solved: 379[Submit][Status][Discuss] Description 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成了一个序列,每个妹子有一个美丽度. Bakser神犇与他打算研究一下这个妹

bzoj 3744 Gty的妹子序列 区间逆序对数(在线) 分块

题目链接 题意 给定\(n\)个数,\(q\)个询问,每次询问\([l,r]\)区间内的逆序对数. 强制在线. 思路 参考:http://www.cnblogs.com/candy99/p/6579556.html 离线的话就如上一题bzoj 3289 Mato的文件管理,可以直接用 莫队 搞,在线的话怎么办呢? 分块大法好. 1 预处理出两个信息: \(f[i][j]\):从 第\(i\)块开始位置 到 位置\(j\) 这段区间的逆序对数 \(s[i][j]\):前\(i\)块中\(\leq

BZOJ 3720: Gty的妹子树

3720: Gty的妹子树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1493  Solved: 502[Submit][Status][Discuss] Description 我曾在弦歌之中听过你, 檀板声碎,半出折子戏. 舞榭歌台被风吹去, 岁月深处尚有余音一缕…… Gty神(xian)犇(chong)从来不缺妹子…… 他来到了一棵妹子树下,发现每个妹子有一个美丽度…… 由于Gty很哲♂学,他只对美丽度大于某个值的妹子感兴趣. 他想知道

Bzoj 3809: Gty的二逼妹子序列 莫队,分块

3809: Gty的二逼妹子序列 Time Limit: 35 Sec  Memory Limit: 28 MBSubmit: 868  Solved: 234[Submit][Status][Discuss] Description Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题. 对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数. 为了方便,我们规定妹子们的美丽度全都在[1,n]中. 给定一个长度为n(1<=n<=100000)的

BZOJ 3720: Gty的妹子树 [树上size分块]

传送门 题意: 一棵树,询问子树中权值大于$k$的节点个数,修改点权值,插入新点:强制在线 一开始以为询问多少种不同的权值,那道CF的强制在线带修改版,直接吓哭 然后发现看错了这不一道树上分块水题... 用王室联邦分块的话需要维护每一个块$dfs$序最小值和最大值,并且插入操作会破坏原来的性质 不如直接按$size$分块,根节点$size<block$就加入根,否则新建块 $size$分块不能保证块的数量,可以被菊花图卡掉,然而本题没有所以就可以安心的写了 每个块维护排序后的值 查询操作,不完整