AtCoder Beginner Contest 174 (全)

AtCoder Beginner Contest 174

A - Air Conditioner

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	cin>>t;
	if(t>=30) cout<<"Yes\n";
	else cout<<"No\n"; 
	return 0;
}

B - Distance

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,d;
	cin>>n>>d;
	int ans=0;
	for(int i=1;i<=n;i++){
		double x,y;
		cin>>x>>y;
		if(sqrt(x*x+y*y)<=(double)d) ans++;
	}
	cout<<ans<<"\n";
	return 0;
}

C - Repsept*

吐槽这个题,不应该放在C

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
    LL k;cin>>k;
	LL x=7%k,ans=1;
    while(1){ 
        if(!x) break;
        if(ans>1000000) break;
        x=x*10+7;
        x%=k;
        ans++;
    }
    if(!x) cout<<ans<<"\n";
    else cout<<"-1\n";
    return 0;
}

D - Alter Altar (思维)

这个D也挺水的,显然符合要求的目标状态就是R都集中在左边,W都集中在右边,那么直接数一下左边有多少W需要与右边R交换就好了。

#include<iostream>
using namespace std;

int main()
{
	int n;
	cin>>n;
	string s;
	cin>>s;
	int r = 0;
	for(int i=0;i<n;i++)
		if(s[i]=='R') r++; //目标状态左侧R的数目
	int ans = 0;
	for(int i=0;i<r;i++) 
		if(s[i]=='W') ans++; //原串中左侧有多少W需要与右侧R交换 
	cout<<ans<<"\n";
	return 0;
}

E - Logs (二分答案)

这个二分答案一眼就看出来了,其实也挺水,就和切木棒的二分几乎都一样了。

#include<bits/stdc++.h>

using namespace std;
const int N = 2e5+7;
int a[N];
int n,k,t;

bool check(int mid)
{
	int ans=0;
	for(int i=1;i<=n;i++){
		if(a[i] > mid) ans += a[i]/mid;	//看看达到此时的最大值需要的最少切割次数
		if(ans>k) return 0;
	}
	return 1;
}

int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i],t=max(t,a[i]);
	
	int l=1,r=t;
	while(l<=r){
		int mid = l+r>>1;
		if(check(mid)) r = mid - 1;
		else l = mid + 1;
	}
	cout<<r+1;
	return 0;
}

F - Range Set Query (离线化+树状数组)

洛谷原题 QAQ,abc是没人管了吗。P1972
当然做法很多,好像主席树也可 QWQ
思路:对于 [ 1 , r ] [1,r] [1,r] 内不同颜色的球的个数,我们有一种思路去解决,我们开一个数组vis,比如在第x个位置出现了3这个颜色,那么我们就只把x位置置为1,之前3出现的位置都归为0,那么在vis中求 [ 1 , r ] [1,r] [1,r] 的前缀和 s u m ( 1 , r ) sum(1,r) sum(1,r) 即是此区间的颜色种类数。
然后我们考虑能不能利用上这个前缀和,由于我们都只保留的每种颜色的最后一个位置,那么在此区间内只有满足需要求的区间的右端点为 r 的前缀和的差值才是正确的,比如 s u m ( 1 , r ) − s u m ( 1 , l − 1 ) sum(1,r)-sum(1,l-1) sum(1,r)sum(1,l1) [ l , r ] [l,r] [l,r] 区间内不同颜色的个数,但是 s u m ( 1 , j ) − s u m ( 1 , i − 1 ) , i ≤ j < r sum(1,j)-sum(1,i-1),i \le j< r sum(1,j)sum(1,i1)ij<r 就不是 [ i , j ] [i,j] [i,j] 的不同颜色个数。
所以我们就直接离线处理询问,把每次询问的区间按右端点从小到大排序,然后在遍历按上述处理即可。
由于要单点修改并求前缀和,所以就是树状数组比较方便了。

#include<bits/stdc++.h>

using namespace std;
const int N = 5e5+7; 

struct Node{
	int l,r;
	int i;
}q[N];

int tr[N];
int n,m;
int a[N],vis[N];
int ans[N];

int lowbit(int x){
	return x&-x;
}

void add(int x,int v){
	for(int i = x;i<=n;i+=lowbit(i))
	tr[i] += v; 
}

int query(int x){
	int ans=0;
	for(int i=x;i;i-=lowbit(i)) ans+=tr[i];
	return ans;
}

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

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&q[i].l,&q[i].r);
		q[i].i = i;
	}
	sort(q+1,q+m+1,cmp);
	int j = 1;
	for(int i=1;i<=m;i++){		//每次求右边界为r的区间
		while(j <= q[i].r){
			if(vis[a[j]]) add(vis[a[j]],-1);
			add(j,1);
			vis[a[j]] = j;
			j++;
		}
		ans[q[i].i] = query(q[i].r) - query(q[i].l-1);
	}
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);   //按询问次序输出
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值