20160319】的考试【线段树水题却WA的飞起

20 篇文章 0 订阅
14 篇文章 0 订阅

据说是老师自己翻译的……虽然全是粘的题2333


Q1

描述:

    农夫John有N头牛,将牛从1到N编号。经过测试,每头牛有一个测试值[Si, Ei].
    有的牛强壮,有的牛虚弱。给两头牛i和j,如果Si <= Sj ,Ej <= Ei 并且 Ei - Si > Ej - Sj, 那么我们认为牛i比牛j强壮。
    问对于每头牛,有多少牛比它强壮.
输入:
    第一行,一个整数N, 表示牛的头数。
    接下来N行, 每行两个整数, Si, Ei, 表示第i头牛的测试值。(0 <= Si < Ei <= 10^5)
    (OJ上多case,以N=0结束)
输出:
    输出N个整数,用空格分开,第i个整数表示有多少牛比第i头牛强壮。
样例输入:
3
1 2
0 3
3 4

样例输出:
1 0 0
数据范围:
    30%数据, 1 <= N <= 10^3
    100%数据,1 <= N <= 10^5
地址:

http://bailian.openjudge.cn/practice/2481

思路:

1)显然,有Si<=Sj, Ej<=Ei 可以推得出来第三个式子只在两只牛两个值都相同的时候才有用
  于是双关键字(Si<Sj, Ei>Ej) 排序,每只牛只影响它后面的,而且数据范围表示并不用离散化

呆马↓

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;	int n;

struct t1{
	int S,E;
	int lab;
	bool operator < (const t1 x)const {
		return S==x.S?E>x.E:S<x.S;
	}
}dt[100057];

int lzy[500557];
void pushdown(int now){
	lzy[now<<1]+=lzy[now],lzy[now<<1|1]+=lzy[now];
	lzy[now]=0;
}

void modify(int now,int l,int r,int L,int R){
	if(!(~R))	return;
	if(L<=l&&r<=R){
		++lzy[now];
		return ;
	}
	if(lzy[now])	pushdown(now);
	int mid=(l+r)>>1;
	if(L<=mid)	modify(now<<1,l,mid,L,R);
	if(mid<R)	modify(now<<1|1,mid+1,r,L,R);
}

int inqry(int now,int l,int r,int loc){
	if(r==l)
		return lzy[now];
	pushdown(now);	
	int mid=(l+r)>>1;
	if(loc<=mid)	inqry(now<<1,l,mid,loc);
	else inqry(now<<1|1,mid+1,r,loc);
}

int ans[100057];
int mx=0;
int main(){
	memset(dt,0,sizeof(dt));
	memset(lzy,0,sizeof(lzy));
	
	freopen("in","r",stdin);
	freopen("out","w",stdout);
	
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d%d",&dt[i].S,&dt[i].E);
		dt[i].lab=i;
		mx=max(mx,dt[i].E);
	}
	sort(dt+1,dt+n+1);
	
	for(int i=1;i<=n;++i){
		if(dt[i].E==dt[i-1].E&&dt[i].S==dt[i-1].S)
			ans[dt[i].lab]=ans[dt[i-1].lab];
		else
			ans[dt[i].lab]=inqry(1,0,mx,dt[i].E);
		modify(1,0,mx,0,dt[i].E);
	}
	
	for(int i=1;i<=n;++i)	printf("%d ",ans[i]);
	
	return 0;
}


Q2

描述:
    在大选中,政府建立了一堵墙给n个候选人贴海报。
    每张海报的高和墙一样高,占据一段连续的墙,并且起点和终点都是整数。
    每位候选人依次贴海报,后面贴的海报会覆盖前面贴的海报,问最后能看到几个人的海报?
输入
    第一行是case数T,对于每个case:
    第一行一个整数n(n <= 10000), 表示候选人数。
    接下来n行,每行两个整数l_i, r_i, 表示第i位候选人贴的海报占据的位置。(1 <= l_i <= r_i <= 10^7)
输出
    输出最后能看见的海报数。
样例输入
1
5
1 4
2 6
8 10
3 4
7 10
样例输出
4

网址:
http://bailian.openjudge.cn/practice/2528

思路:

1)水题,但是老师改了数据范围于是跪了【线段树开小了,表示堆式的还是多开一点空间比较好orzorz

呆马↓

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;	int T,n;
const int MAXN=100057;

int l[MAXN],r[MAXN];
vector<int> mem;

int clr[MAXN];
int lzy[MAXN*5];

void pushdown(int now){
	lzy[now<<1]=lzy[now<<1|1]=lzy[now];
	lzy[now]=0;
}

void modify(int now,int ll,int rr,int L,int R,int q){
	if(L<=ll&&rr<=R){
		lzy[now]=q;
		return ;
	}
	if(lzy[now])	pushdown(now);
	int mid=(ll+rr)>>1;
	if(L<=mid)	modify(now<<1,ll,mid,L,R,q);
	if(mid<R)	modify(now<<1|1,mid+1,rr,L,R,q);
}

int tag[MAXN];

void doit(int now,int ll,int rr){
	if(ll==rr){
		tag[lzy[now]]=1;
		return ;
	}
	if(lzy[now])	pushdown(now);
	int mid=(ll+rr)>>1;
	doit(now<<1,ll,mid);
	doit(now<<1|1,mid+1,rr);
}

int main(){
	freopen("in","r",stdin);
	freopen("out","w",stdout);
	
	scanf("%d",&T);
	while(T--){
		memset(lzy,0,sizeof(lzy));
		memset(tag,0,sizeof(tag));
		scanf("%d",&n);
		for(int i=1;i<=n;++i){
			scanf("%d%d",&l[i],&r[i]);
			mem.push_back(l[i]);
			mem.push_back(r[i]);
		}
		sort(mem.begin(),mem.end());
		unique(mem.begin(),mem.end());
		for(int i=1;i<=n;++i){
			l[i]=lower_bound(mem.begin(),mem.end(),l[i])-mem.begin()+1;
			r[i]=lower_bound(mem.begin(),mem.end(),r[i])-mem.begin()+1;
		}
		int mx=mem.size();
		mem.clear();
		for(int i=1;i<=n;++i)
			modify(1,1,mx,l[i],r[i],i);
		doit(1,1,mx);
		int cnt=0;
		for(int i=1;i<=n;++i)	if(tag[i])	++cnt;
		printf("%d\n",cnt);
	}
	return 0;
}

Q3

描述
    一个平面上有若干整数坐标的点。
    Stan和Ollie玩游戏,Stan首先画一条竖直线,这条竖直线必须经过平面上的某个点。 Ollie再画一条水平线,这条线必须经过Stan所画线所经过的其中一个点。
    这样,平面被分为4个象限, Stan的得分为第一, 三象限中的点的个数, Ollie的得分为第二、四象限中的点的个数。 不计算所画线上的点。
    Stan和Ollie想最大化他们的得分。Stan想最大化在最坏情况下的最高得分。
    
输入
    多case。
    每个case,第一行,一个整数n(1 < n < 2*10^5),表示平面上点的个数。
    接下来n行,每行两个整数x, y, 表示每个点的坐标。没有两个点的坐标相同。
    输入以n = 0结束
    
输出
    对于每个case,输出一行(格式参看样例输出)。 第一个整数是Stan在最坏情况的最高得分, 其他的整数是Ollie的可能得分, 按增序输出。

样例输入
11
3 2
3 3
3 4
3 6
2 -2
1 -3
0 0
-3 -3
-3 -2
-3 -4
3 -7
0
样例输出
Stan: 7; Ollie: 2 3;

网址:
http://bailian.openjudge.cn/practice/2464/

思路:

        null(x    【表示考试的时候浪的很开心orzorz这道题欢快地只是看了一眼233 回家再改



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值