2020年河南省第二届CCPC大学生程序设计竞赛

A班委竞选

原题链接

结构体排序。

#include<bits/stdc++.h>

using namespace std;
const int N=1e3+5;
int vis[105];
struct node{
	int id,pos,val;
	bool operator<(const node&rhs)const{
		if(pos==rhs.pos){
			if(val==rhs.val){
				return id<rhs.id;
			}else return val>rhs.val;
		}else return pos<rhs.pos;
	}
}a[N];
int main()
{
	int n,m,pos,val;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>pos>>val;
		a[i].id=i;a[i].pos=pos;a[i].val=val;
	}
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++){
//		cout<<a[i].pos<<' '<<a[i].val<<' '<<a[i].id<<'\n';
		if(!vis[a[i].pos]){
			cout<<a[i].id<<' ';
			vis[a[i].pos]=1;
		}
	}
  return 0;
}

C我得重新集结部队

思路:硬模拟。一开始思路理解错了,用队列模拟,后来又读了好几遍题才理清思路。对异虫和折跃狂分析,用结构体存下来他们的信息,然后就模拟事件,出现折跃狂就找最近的异虫对范围内攻击。最后判断。

坑点:

  1. 寻找最近距离时dist>=2e18,因为极端情况就是2e18,因为这wa了半天没找到原因
  2. 使用long long 存储数据,距离也是,因为在double下精度会丢失,判断距离的平方即可
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=4e3+5;
struct node{
	ll x,y,type,h,r,atk,leave;
	//x,y坐标,type:0异虫 1 人类	h:异虫生命值 r 攻击范围 atk 攻击 leave 0离开 1留下 
}a[N];
ll get_dist(ll x1,ll y1,ll x2,ll y2 )
{
	ll d1=x1-x2;
	ll d2=y1-y2;
	return d1*d1+d2*d2;
}
int main()
{
	ll x,y,h,op,n,cnt=1,atk,r;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>op;
		if(op==1){
			cin>>x>>y>>h;
			a[cnt].type=0;//异虫 
			a[cnt].x=x;a[cnt].y=y;a[cnt].h=h;
			cnt++;
		}else{
			cin>>x>>y>>atk>>r;
			a[cnt].type=1;//人 
			a[cnt].x=x;a[cnt].y=y;a[cnt].atk=atk;a[cnt].r=r;
			int pos=-1;//离异虫最近的位置
			ll dist=2e18;
			for(int i=1;i<cnt;i++){
				if(a[i].type==1||a[i].type==0&&a[i].h<=0)continue;//人或者异虫已死 
				ll tdist=get_dist(a[cnt].x,a[cnt].y,a[i].x,a[i].y);
				if(dist>tdist){
					pos=i;dist=tdist;
				} 
			}
			a[cnt].leave=1;//默认人会留下,下面异虫没死,人就要离开 
			if(pos==-1){//异虫全死亡 
				a[cnt].leave=1;//人留下 
			}else{//对r范围内的异虫进行攻击 
				for(int i=1;i<cnt;i++){
					if(a[i].type==1||a[i].type==0&&a[i].h<=0)continue;//人或者异虫死亡
					ll tdist=get_dist(a[pos].x,a[pos].y,a[i].x,a[i].y);
					if(r*r>=tdist){
						a[i].h-=3*atk;
						if(a[i].h>0)a[cnt].leave=0;
					} 
				}
			} 
			cnt++;
		}
	}
	for(int i=1;i<cnt;i++){
		if(a[i].type==0){//异虫 
			if(a[i].h<=0)cout<<"No";
			else cout<<"Yes";
		}else{//人 
			if(a[i].leave==0)cout<<"No";
			else cout<<"Yes";
		} 
		cout<<'\n';
	}
  return 0;
}
/*

5
1 0 0 4
1 0 1 8
2 1 0 1 1
2 1 0 1 1
2 1 0 1 1

No
No
No
No
Yes
*/

E发通知

原题链接

思路:差分+离散化(扫描线)

通过对时间段左右区间+1,-1。然后求前缀和的过程增加的就是同学的数量,同时用sum进行异或,当从cnt=1到cnt=2时,sum=8^2,再到1时,此时sum=8^2^8=2。所以一直求异或和,并统计同学人数,更新答案即可。

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<ll,ll>PI;
const int N=2e5+5;
map<ll,PI>::iterator it;
map<ll,PI>mp;
int main()
{
	ll n,k,l,r,w;
	cin>>n>>k;
	for(int i=0;i<n;i++){
		cin>>l>>r>>w;
		mp[l].first++;
		mp[r+1].first--;
		mp[l].second^=w;
		mp[r+1].second^=w;
	}
	ll cnt=0,sum=0,maxx=-1;
	for(it=mp.begin();it!=mp.end();it++){
		cnt+=it->second.first;
		sum^=it->second.second;
		if(cnt>=k){
			maxx=max(maxx,sum);
		}
	}
	cout<<maxx<<'\n';
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43566782/article/details/113774624