Problem M. Heaviside Functionz

题目意思很简单明了,直接做肯定tle


注意到s的值只有正负1   因此可以把s=1的a全部放在一起  s=-1的全放在一起,假设个数分别是num1,num2

从而对于每一个m

sum=0;

在s=1 中的a  二分找到一个m>=a

此时sum+=(a的下标);

在s=-1中的a 二分找到一个(-m) >=a

此时sum+=(a的下标);

从而 成了O(m*num1*log(num1)+m*num2*log(num2))


关键就是二分答案


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;

int tm1[200000+5];
int tm2[200000+5];

int nm[200000+5];

int main()
{
	
	int n;
	cin>>n;
	int i,j;
	int c1,c2;
	int ok1=0;
	int ok2=0;
	for (i=1;i<=n;i++)
	{
		scanf("%d %d",&c1,&c2);
		if (c1==1)
		{
			tm1[++ok1]=c2;
		}
		else
		{
			tm2[++ok2]=c2;
		}
	}
	sort(tm1+1,tm1+ok1+1);
	sort(tm2+1,tm2+ok2+1);
	
	int m;
	cin>>m;
	for (i=1;i<=m;i++)
	{
		scanf("%d",&nm[i]);
		
	}
	
	
	
	
	__int64  sum;
	
	for (i=1;i<=m;i++)
	{
		sum=0;	 
		int l=1;
		int r=ok1;
		while(l<=r)
		{
			int mid =(l+r)/2;
			if (nm[i]==tm1[mid]||r-l==1||r-l==0)
			{
				if (nm[i]==tm1[mid])
				{
					int tt=mid;
					while(tm1[tt]==nm[i]&&tt<=r)  	
						tt++; 
					sum+=tt-1; 
					break;
				} 
				else
				if ( r-l==0)
				{
					if (nm[i]<tm1[l])
					{
						sum+=l-1; 
					}
					else
						sum+=r;
					
					break;
				}
				else
					if (r-l==1)
					{
						if (nm[i]<tm1[l])
						{
							sum+=l-1;
						}
						else
						{
							if (nm[i]<tm1[r])
							{
								sum+=r-1;
							}
							else
								sum+=r;  
						}
						break;
					}
					
			}
			else
				
				if (nm[i]>tm1[mid])
				{
					l=mid+1;
				}
				else
				{
					r=mid-1;
					
				}
				
				
				
		}

			  l=1;
		  r=ok2;
		while(l<=r)
		{
			int mid =(l+r)/2;
			if (nm[i]*(-1)==tm2[mid]||r-l==1||r-l==0)
			{
				if (nm[i]*(-1)==tm2[mid])
				{
					int tt=mid;
					while(tm2[tt]==nm[i]*(-1)&&tt<=r)  	tt++; 
					sum+=tt-1; 
					break;
				} 
				else
				if ( r-l==0)
				{
					if (nm[i]*(-1)<tm2[l])
					{
						sum+=l-1;
					}
					else
						sum+=r; 

					break;
				}
				else
					if (r-l==1)
					{
						if (nm[i]*(-1)<tm2[l])
						{
							sum+=l-1;
						}
						else
						{
							if (nm[i]*(-1)<tm2[r])
							{
								sum+=r-1;
							}
							else
								sum+=r; 
						
							
						}
							break;
					}
					
			}
			else
				
				if (nm[i]*(-1)>tm2[mid])
				{
					l=mid+1;
				}
				else
				{
					r=mid-1;
					
				}
				
				
				
		}
		

		
		printf("%I64d\n",sum);
		
	}
	
	return 0;
	
	
	
} 


刚看到一个upper_bound函数,,,作用就是二分查找 方便不少。

//iterator lower_bound(a.begin(), a.end(), x): 返回一个迭代器,指向键值>= key的第一个元素。
//iterator upper_bound(a.begin(), a.end(), x):返回一个迭代器,指向键值> key的第一个元素。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;

int tm1[200000+5];
int tm2[200000+5];

int nm[200000+5];

int main()
{
	
	int n;
	cin>>n;
	int i,j;
	int c1,c2;
	int ok1=0;
	int ok2=0;
	for (i=1;i<=n;i++)
	{
		scanf("%d %d",&c1,&c2);
		if (c1==1)
		{
			tm1[++ok1]=c2;
		}
		else
		{
			tm2[++ok2]=c2;
		}
	}
	sort(tm1+1,tm1+ok1+1);
	sort(tm2+1,tm2+ok2+1); 
	int m;
	cin>>m;
	for (i=1;i<=m;i++)
	{
		scanf("%d",&nm[i]); 
	} 
	
	__int64  sum;
	
	for (i=1;i<=m;i++)
	{
		sum=0;	  
    	 sum+=upper_bound(tm1+1,tm1+1+ok1,nm[i])-&tm1[1];
		sum+=upper_bound(tm2+1,tm2+1+ok2,(-1)*nm[i])-&tm2[1];
		
		printf("%I64d\n",sum);
		
	}
	
	return 0;
	
	
	
} 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值