POJ-3145-Harmony Forever-线段树暴力

题意: 

对一个集合,有两种操作,

一:将某个元素加入集合中 

二:个是问当前集合中mod y 最小的数,如果有多个,输出最近加入的那个元素的输入时间,在本题指的是该元素加入集合时操作一的次数

当y比较大

每次对[0,y-1]、[y,2y-1]...每个长度为y的区间查询最小的存在的数。。。最后比较得到答案

y比较小的话,如果这样遍历 区间最多会有  500000/y个。。所以不如直接遍历出现过的所有数。最多只有4W个。。。。



#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const int inf=2147483647;
const double pi=acos(-1.0);
double eps=0.000001; 


struct tree
{
	int st_min[500005*4];
	
	inline int minn(int a,int b) { return a>b?b:a; }
	inline int maxx(int a,int b) { return a>b?a:b; }
	void pushup(int rt)
	{
		st_min[rt]=minn(st_min[rt<<1],st_min[rt<<1|1]);
	}
	void update(int l,int r,int rt,int num,int val)
	{
		if (l==r&&r==num)
		{st_min[rt]=val;return;}
		int m=(l+r)>>1;
		if (num<=m)
			update(l,m,rt<<1,num,val);
		else
			update(m+1,r,rt<<1|1,num,val);
		pushup(rt);
	}
	int query(int ql,int qr,int l,int r,int rt)
	{
		if (ql>r||qr<l)  return inf;
		if (ql<=l&&qr>=r)
			return st_min[rt];
		int m=(l+r)>>1;
		int ret1=query(ql,qr,l,m,rt<<1);
		int ret2=query(ql,qr,m+1,r,rt<<1|1);
		return minn(ret1,ret2); 
	}
	void build(int l,int r,int rt)
	{
		st_min[rt]=inf;
		if (l==r) return ;
		int m=(l+r)>>1;
		build(l,m,rt<<1);
		build(m+1,r,rt<<1|1);
	}
};
tree tp;
int tm[500005];
int vis[500005];  
void solve(int y,int cun)
{		
	int i;
	if (y<=5000)
	{
		int ans=inf;
		int ans_id;
		for (i=cun;i>=1;i--)
		{ 
				if (vis[i]%y<ans)
				{
					ans=vis[i]%y;
				 	ans_id=i;
				}
				if (ans==0) break;
		}
		if (ans==inf) printf("-1\n");
		else
			printf("%d\n",ans_id); 
		return ;
	}
	else
	{
		int ans=inf;
		int ans_id;
		for (i=0;i<=500000+y;i+=y)
		{
			int high=i+y-1;
		//	if (high>500000)  high=500000;
			int xx=tp.query(i,high,1,500000,1);
			if (xx==inf) continue;
			if (xx%y<=ans) 
			{
				if (ans==xx%y)
				{
					if (tm[xx]>ans_id)
						ans_id=tm[xx] ;
				}
					else
						ans_id=tm[xx];
				ans=xx%y;
			}
		}
		if (ans==inf) printf("-1\n");
		else
			printf("%d\n",ans_id);  
	} 
}
int main()
{
	
	int t;
	int cnt=1;
	while(cin>>t)
	{
		if (!t) break; 
		memset(tp.st_min,0,sizeof(tp.st_min));
		memset(tm,0,sizeof(tm));
		
		if (cnt!=1) printf("\n");
		printf("Case %d:\n",cnt++);
		getchar();  
		int i;
		tp.build(1,500000,1); 
		
		int cun=0;
		int yy;
		char ty[15];
		for (i=1;i<=t;i++)
		{
			scanf("%s%d", ty,&yy); 
			if (ty[0]=='B')
			{ 
				cun++;
				tm[yy]=cun;
				tp.update(1,500000,1,yy,yy);	
				 vis[cun]=yy;
			}
			else
			{ 
				solve(yy,cun);
			}
		} 
		
	}
	return 0; 
}


你可能感兴趣的:(POJ-3145-Harmony Forever-线段树暴力)