Yeahpeng's inequality

Yeahpeng's inequality

Time Limit:3000MS  Memory Limit:65536K
Total Submit:35 Accepted:5

Description

Yeahpeng is not good at inequality. Unfortunately, there are many inequalities in his homework and they make him be in trouble. Cornered yeah wants your help. 
There are n inequalities in total and the form is: 
Op x 
Op is one of {>=, >, =, <, <=}, x is an integer. What he wants to know is how many inequalities can be satisfied at most in the first i inequalities. 

Input

Input contains multiple test cases. 
In each test case, the first line is a integer n(1 <= n <= 50,000) 
The following n line is the inequalities [op x]. 

Output

For each test case print n lines. An integer in each line, the maximum numbers can be satisfied in the first i inequalities.

Sample Input

5
<= 10
< 9
> 6
>= 7
= 8

Sample Output

1
2
3
4
5 
题意:给定n个不等式,第i次询问前i个不等式中可以有几个共存。

思路:每个不等式对应了一个区间,即询问区间上被覆盖次数最多的点被覆盖了几次。

解法:先将所有的不等式读入,然后将x离散化一下,把>,<强制转化为>=,<=,然后把区间放到线段树上,每次更新一个区间,树根的max值即为整段区间上被覆盖次数最多的点的覆盖次数。因为每次都要覆盖,可以打一下lazy标记。

AC代码:

//************************************************************************//
//*Author : Handsome How                                                 *//
//************************************************************************//
//#pragma comment(linker, "/STA	CK:1024000000,1024000000")
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
using namespace std;
typedef long long ll;
//----------------------------------------------------------
/*
	将不等式的x离散化一下,对于每一个出现的数,映射为2*他的排名  即i=rank[i]*2 
	那么 >=x 覆盖的区间为[2*rank[x],maxlen] 
	>x	覆盖的区间为[2*rank[x]+1,maxlen] 
	<=x	覆盖的区间为[0,2*rank[x]] 
	<x  覆盖的区间为[0,2*rank[x]-1] 
	建立线段树维护区间内覆盖点的次数 
	那么根结点的max值即为所有区间内被覆盖最多点的次数 
*/
const int maxn = 50000+5;
int n,maxlen;
map<ll,int>rk;
struct Node{
	ll v;
	char op[5];
}node[maxn+5],ori[maxn+5];//分别记录排序后的以及原来的不等式 

struct Tree{
	int l;
	int r;
	int max;
	int lazy;
}tree[maxn*4*4+5];

void build(int l,int r,int root){			 
	tree[root].l = l;tree[root].r=r;
	tree[root].max = 0;
	tree[root].lazy = 0;
	if(l==r) return;
	int mid = (l+r)>>1;
	build(l,mid,root<<1);
	build(mid+1,r,root<<1|1);
}

bool cmp(Node a,Node b){return a.v<b.v;}

void pushdown(int root){
	int lazy = tree[root].lazy ;
	tree[root].lazy = 0;
	tree[root<<1].max +=lazy;
	tree[root<<1].lazy +=lazy;
	tree[root<<1|1].max +=lazy;
	tree[root<<1|1].lazy +=lazy;
}

void init(){
	rk.clear();
	int count = 1;
	sort(node+1,node+1+n,cmp);						
	for(int i=1;i<=n;i++){
		if(rk[node[i].v]==0){		//离散化  将  >=a  的标记为偶数2n 这样如果>a 可强制转化为>=2n+1 
			rk[node[i].v]=count*2;	//将<a 强制转化为<=2n-a 
			count++;	
		}
	}
	maxlen=count*2+2;
	build(1,maxlen,1);	
}

void cover(int l,int r,int root){
	if(tree[root].l==tree[root].r){		 
		if(tree[root].l>=l&&tree[root].l<=r)		//找到最后单点的叶子 判断是否被区间覆盖
		tree[root].max++;
		return;
	}
	if(l>tree[root].r||r<tree[root].l)return;		//超出范围 不能覆盖 
	if(tree[root].l>=l&&tree[root].r<=r){			//打lazy标记 
		tree[root].max++;
		tree[root].lazy++;
		return;
	}
	pushdown(root);
	cover(l,r,root<<1);
	cover(l,r,root<<1|1);
	tree[root].max = max(tree[root<<1].max ,tree[root<<1|1].max); 
}

int main()
{
	while(scanf("%d",&n)!=EOF){
		for(int i=1;i<=n;i++){
			scanf("%s",node[i].op);
			strcpy(ori[i].op,node[i].op);
			scanf("%d",&node[i].v);
			ori[i].v=node[i].v;		//读入不等式并拷贝一份 
		}
		init();					
		for(int i=1;i<=n;i++){
			if(ori[i].op[0]=='=') cover(rk[ori[i].v],rk[ori[i].v],1);
			else if(ori[i].op[0]=='>'&&ori[i].op[1]=='=') cover(rk[ori[i].v],maxlen,1);
			else if(ori[i].op[0]=='<'&&ori[i].op[1]=='=') cover(0,rk[ori[i].v],1);
			else if(ori[i].op[0]=='>')	cover(rk[ori[i].v]+1,maxlen,1);
			else cover(0,rk[ori[i].v]-1,1);
			printf("%d\n",tree[1].max);
		}		
	}
	return 0;
}


你可能感兴趣的:(Yeahpeng's inequality)