[BZOJ3578]GTY的人类基因组计划2(hash+set)

题目描述

传送门

题解

用一个set维护当前所有可以做实验的房间
对于每一坨人搞一个hash值(据说可以随机一些大整数,我用了一个S进制数胡搞)
然后用一个map记录一下每一个hash值是否出现过
当把一个人挪到另一个房间去的时候重新计算一下hash值,并维护set
upper_bound找到大于它的最小的
lower_bound找到大于等于它的最小的

代码

#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define UL unsigned long long
#define N 100005

const UL S=2000001001LL;
int n,m,q,ans;
int loc[N],cnt[N];
UL mi[N],hash[N];
set <int> s;
map <int,bool> mp;

int main()
{
    scanf("%d%d%d",&n,&m,&q);
    mi[0]=1;
    for (int i=1;i<=n;++i)
    {
        mi[i]=mi[i-1]*S;
        hash[1]+=(UL)i*mi[i];
        loc[i]=1;
    }
    s.insert(0);s.insert(m+1);
    s.insert(1);cnt[1]=n;
    for (int i=1;i<=q;++i)
    {
        char opt=getchar();
        while (opt!='C'&&opt!='W') opt=getchar();
        int x,y;scanf("%d%d",&x,&y);

        if (opt=='C')
        {
            --cnt[loc[x]];
            if (hash[loc[x]]&&!mp[hash[loc[x]]])
                s.erase(loc[x]);
            hash[loc[x]]-=(UL)x*mi[x];
            if (hash[loc[x]]&&!mp[hash[loc[x]]])
                s.insert(loc[x]);

            ++cnt[y];
            if (hash[y]&&!mp[hash[y]])
                s.erase(y);
            hash[y]+=(UL)x*mi[x];
            if (hash[y]&&!mp[hash[y]])
                s.insert(y);

            loc[x]=y;
        }
        else
        {
            set<int>::iterator l,r,t,del;
            ans=0;
            l=s.lower_bound(x);r=s.upper_bound(y);
            for (t=l;t!=r;)
            {
                ans+=cnt[*t];
                mp[hash[*t]]=1;
                del=t;++t;
                s.erase(del);
            }
            printf("%d\n",ans);
        }
    }
}

你可能感兴趣的:(题解,hash,stl)