2016 UESTC Training for Data Structures

就做了4题,其他的感觉好难!!QAQ

卿学姐与公主

某日,百无聊赖的卿学姐打开了某11区的某魔幻游戏
在这个魔幻的游戏里,生活着一个美丽的公主,但现在公主被关押在了魔王的城堡中。
英勇的卿学姐拔出利刃冲向了拯救公主的道路。
走过了荒野,翻越了高山,跨过了大洋,卿学姐来到了魔王的第一道城关。
在这个城关面前的是魔王的精锐部队,这些士兵成一字排开。
卿学姐的武器每次只能攻击一个士兵,并造成一定伤害,卿学姐想知道某时刻从L到R这个区间内,从开始到现在累计受伤最严重的士兵受到的伤害。
最开始每个士兵的受到的伤害都是0
Input

第一行两个整数N,Q
表示总共有N个士兵编号从1到N,和Q

个操作。

接下来Q
行,每行三个整数,首先输入一个t,如果t是1,那么输入p,x,表示卿学姐攻击了p这个位置的士兵,并造成了x的伤害。如果t是2,那么输入L,R,表示卿学姐想知道现在[L,R]

闭区间内,受伤最严重的士兵受到的伤害。

1≤N≤100000
1≤Q≤100000
1≤p≤N
1≤x≤100000
1≤L≤R≤N

Output

对于每个询问,回答相应的值

样例输入

5 4
2 1 2
1 2 4
1 3 5
2 3 3

样例输出

0
5

Hint
注意可能会爆int哦

题解:第一题还是很简单的,单点修改,区间查询的线段树

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define LiangJiaJun main
#define LL long long
using namespace std;
LL tr[400004];
int n,q,up=1;
LL  query(int l,int r){
	LL ans=0;
	for(l=l+up-1,r=r+up+1;r-l>1;r>>=1,l>>=1){
		if(~(l&1)) ans=max(ans,tr[l+1]);
		if(r&1) ans=max(ans,tr[r-1]);
	}
	return ans;
}
void change(int p,LL x){
	 int now = p + up ;
	 tr[now] += x;
	 now >>= 1;
	 while(now >= 1){
		tr[now] =max( tr[now<<1] , tr[now<<1|1] );
		now >>= 1;
	 }
}
int LiangJiaJun(){
	scanf("%d%d",&n,&q);
	while(up<n+2)up<<=1;
	memset(tr,0,sizeof(tr));
	while(q--){
		int t,p,l,r;LL x;
		scanf("%d",&t);
		if(t==1){
			scanf("%d%lld",&p,&x);
			change(p,x);
		}
		if(t==2){
			scanf("%d%d",&l,&r);
			printf("%lld\n",query(l,r));
		}
	}
	return 0;
}

卿学姐与诡异村庄

日复一日,年复一年,春去秋来。
卿学姐终于从天行廖那里毕业啦。出山的卿学姐首先来到了一个诡异的村庄。
在这个村庄中,只有两种人,一种是好人,一种是坏人。
好人只说真话,坏人只说假话。
村庄虚伪的平静由于卿学姐的到来,终于被打破了。
人们开始互相指控,每个人都会说另外一个人是否是好人。
卿学姐修行途中只学会了膜法,却不谙世事,所以卿学姐无法确认哪些人是好人,哪些人是坏人。
但是机智的卿学姐意识到可以通过这些人的指控来分辨。
现在告诉你村庄中每个人指控谁是否为好人,请问是否有个合理的分类能够符合所有的指控。
Input
第一行一个整数N
,表示村庄总共有N个人,村民从1开始编号到N
1≤N≤100000
接下来N行,每行两个整数,ai,t,如果t是1,那么说明第i个人认为第ai个人是好人。如果t是2,那么说明第i个人认为第ai
个人是坏人。(1≤ai≤N)
Output
如果存在一个好人坏人的分类能够满足所有的指控,那么输出"Time to show my power",否则输出"One face meng bi"

样例输入1:

3
2 2
3 1
1 2

样例输出1:

Time to show my power

样例输入2:

3
2 2
3 2
1 2

样例输出2:

One face meng bi

题解:并查集入门。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<set>
#define LiangJiaJun main
#define LL long long
using namespace std;
bool ok=1;
int a[200004],t[200004],n;
int p,q,f[200014];
int find(int x){return (f[x] == x)?f[x]:f[x] = find(f[x]);}
int LiangJiaJun(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&t[i]);
	for(int i=1;i<=2*n;i++) f[i]=i;
	for(int i=1;i<=n;i++){
		if(t[i] == 1) {
			p=find(i);q=find(a[i]);
			if(p!=q)f[p]=q;
			p=find(i+n);q=find(a[i]+n);
			if(p!=q)f[p]=q;
		}
		else{
			p=find(i);q=find(a[i]+n);
			if(p!=q)f[p]=q;
			p=find(i+n);q=find(a[i]);
			if(p!=q)f[p]=q;
		}
		if(find(i)==find(i+n) || find(a[i])==find(a[i]+n)){ok=0;break;}
	}
	if(ok)puts("Time to show my power");
	else puts("One face meng bi");
	return 0;
}

卿学姐与魔法

“你的膜法也救不了你”——蛤
在去拯救公主的道路上,卿学姐披荆斩棘,刀刃早已锈迹斑斑。
一日卿学姐正在为武器的问题发愁,碰到了正在赏树的天行廖。
天行廖嘴角微扬,似乎看穿了卿学姐的心思,故意在此等待。
“少年,你渴望掌握雷电的力量吗?”天行廖如是问道。
已经差不多是条咸鱼的卿学姐欣然答应了。于是卿学姐开始跟随魔法大师天行廖学习魔法的力量。
刚入门的卿学姐发现,每个魔法都是由两种基本元素构成的,A元素和B元素。
而每个魔法的魔力是合成这个魔法的A元素和B元素的大小的和。
例如一个大小为3的A元素和一个大小为6的B元素,能构成一个魔力为9的魔法。
现在卿学姐收集了N个A元素和N个B元素。敏锐的卿学姐立刻发现他能组合出N∗N种魔法。
谦虚的卿学姐并不希望自己太跳,所以他准备将这N∗N
种魔法中的最小的N种展示给天行廖检查。
现在卿学姐想知道,这N∗N种魔法中最小的N种是什么。

当然,得从小到大输出哦~
Input

第一行一个整数N

接下来一行有N
个数,表示N个A元素

接下来一行有N
个数,表示N个B元素

1≤N≤100000

1≤A[i],B[i]≤1000000000

Output

输出N行,每行一个整数
代表N∗N种魔法中最小的N个

样例输入

5
1 3 2 4 5 
6 3 4 1 7

样例输出

2
3
4
4
5

题解:同 [洛谷P1631]序列合并/[codevs1245]最小的N个和
链接:http://blog.csdn.net/dxyinme/article/details/52211000

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#define LiangJiaJun main
#define LL long long
#define pa pair<LL,int>
using namespace std;
priority_queue<pa , vector<pa> , greater<pa> >q;
LL A[100004],B[100004],ans[100004];
int n,qs[100004],cnt=0;
int LiangJiaJun(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%lld",&A[i]);
	for(int i=1;i<=n;i++)scanf("%lld",&B[i]);
	sort(A+1,A+n+1);sort(B+1,B+n+1);
	for(int i=1;i<=n;i++){
		q.push(make_pair(A[1]+B[i],i));
		qs[i] = 1;
	}
	cnt=0;
	while(cnt <= n){
		pa x = q.top();q.pop();
		ans[++cnt] = x.first;
		q.push(make_pair(A[++qs[x.second]]+B[x.second],x.second));
	}
	for(int i=1;i<=n;i++)printf("%lld\n",ans[i]);
	return 0;
}


郭大侠与Rabi-Ribi

最近郭大侠迷上了玩Rabi-Ribi这个游戏。
Rabi-Ribi呢,是一个打兔子的动作冒险游戏,萌萌哒的兔子在地上跑来跑去,好萌好萌呀~
这个游戏是这样玩的,郭大侠作为一个主角,拿着一个小锤子,他的目标是敲晕兔子,然后最后把这些敲晕的兔子都带回家。

当然咯,郭大侠想带回的兔子的总价值最高~

但是,兔子实在是太多了,郭大侠的锤子每一秒钟只能敲晕一只兔子,而且每一只兔子只会在地面上逗留a[i]秒,在a[i]秒之后,这一只兔子就会跑回自己的小窝里面。
所以郭大侠面临一些抉择,希望你能帮助他。
Input

第一行包含一个整数N
表示有N个兔子在地上跑来跑去。
第二行N个用空格分隔的整数a[i]
表示第i只兔子冒出后停留的时间
第三行N个用空格分隔的整数v[i]表示第i只兔子的价值。

1≤N≤100000
1≤a[i]≤5000
1≤v[i]≤1000

Output
输出郭大侠最多能获得的价值是多少

样例输入1:

5
5 3 6 1 4
7 9 2 1 5

样例输出1:

24

样例输入2:

3
1 1 1
1 2 3

样例输出2:

3

题解:我们先把所有兔子丢到一个以t为关键字的小头堆内,然后每一次取出堆头,如果当前时间小于当前兔子的消失时间,那么就将兔子丢到一个以v为关键字的小头堆中。如果当前时间大于等于当前兔子消失的时间,那么将其与以v为关键字的小头堆的堆头比较v的值,如果比堆头大,那么就将堆头兔子踢掉,将当前兔子加入堆中。计算结果的时候,只要将以v为关键字的小头堆内的兔子的v值都加起来就是答案了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#define LiangJiaJun main
#define LL long long
#define pa pair<int,int>
using namespace std;
priority_queue<pa , vector<pa> , greater<pa> >q,qf;
int n,tn=0,ans=0;
struct data{
	int w,t;
}a[100004];
int LiangJiaJun(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i].t);
	for(int i=1;i<=n;i++)scanf("%d",&a[i].w);
	for(int i=1;i<=n;i++)q.push(make_pair(a[i].t,a[i].w));
	while(!q.empty()){
		pa x = q.top();q.pop();
		if(x.first>tn){
			tn ++;qf.push(make_pair(x.second,x.first));
		}
		else {
			if(!qf.empty()&&x.second > qf.top().first){
				qf.pop(); qf.push(make_pair(x.second,x.first));
			}
		}
	}
	ans = 0;
	while(!qf.empty()){
		ans += qf.top().first;
		qf.pop();
	}
	printf("%d\n",ans);
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值