【bzoj 3578】 GTY的人类基因组计划2(STL的应用)

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

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 323   Solved: 145
[ 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

[ Submit][ Status][ Discuss]



【题解】【STL的应用,一改往常一用STL就荣获TLE的经历啊,看来以前还是使用的不够优越】

【这道题,先给所有的人随机一个值,因为是给一个集合判重,所以判重的时候,将几个人的值异或起来,用map判断是否出现过;将每一次移动后合法的集合即房间号存在set里,每一次移动时,先将相关的两个房间的序号先从set里删掉,再将合法的加入。

  记录:每个房间的人数,每个人的编号,每个房间的当前异或值。】


#include<map>
#include<set>
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
set<int>s;//存合法的房间号 
map<long long,bool>mp;//判重 
long long  num[100010],p[1000010],b[1000010],h[1000010];
int n,m,q;

int main()
{
	int i,j;
	srand(1289);

	scanf("%d%d%d\n",&n,&m,&q);
	for(i=1;i<=n;++i) num[i]=(long long)rand()*rand()%1000000000*(rand()*rand()%2000000000);//给每个人随机一个值 
	s.insert(1);//因为刚开始所有人都在第一个房间,先将第一个房间加入set 
	for(i=1;i<=n;++i) h[1]^=num[i],p[1]++,b[i]=1;//h存当前房间的异或值;p存当前房间的人数;b存当前每个人在哪个房间 
	for(i=1;i<=q;++i)//询问和操作总共不超过10^5,且每次操作只移动一个人,所以范围可以使用STL 
	 {
	    char c;
	 	int x,y;
	 	scanf("%c",&c);
	 	scanf("%d%d\n",&x,&y);
	 	if(c=='C')
	 	  {
	 	  	if(b[x]==y) continue;//看操作后是否换了房间 
	 	  	s.erase(b[x]); s.erase(y);//将原来的状态移出set 
	 	  	
	 	    h[b[x]]^=num[x];
	 	    p[b[x]]--;
	 	    if (!mp[h[b[x]]]) s.insert(b[x]);
	 	    
	 	    h[y]^=num[x];
	 	    p[y]++;
	 	    if (!mp[h[y]]) s.insert(y);
	 	    
	 	    b[x]=y;
	 	  }
	 	 else
	 	  if(c=='W')
	 	   {
	 	     int ans=0;
			 set<int>::iterator it=s.lower_bound(x);
			 for(;it!=s.end()&&*it<=y;it=s.lower_bound(x))
			  {
			  	mp[h[*it]]=1;
			  	ans+=p[*it];
			  	s.erase(it);
			  }	
			 printf("%d\n",ans);
	 	  }
	 }
	 return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值