2021 Niu Ke Winter Holiday Algorithm Basic Training Camp 2 G- Niu Niu and competition awards (difference)

Topic link: click here~

Topic

  • n teams, m questions, the number of teams for each question is just continuous
  • The m line contains two numbers ai, bi, which means that these teams in the interval [ai, bi] have passed the ith problem
  • The players are sorted in descending order \left \lceil n / 10 \right \rceilby the amount of questions, the first \left \lceil n / 4 \right \rceilis the amount of gold medal line, the number is the amount of silver medal line, and the \left \lceil n / 2 \right \rceilnumber is the amount of bronze medal line
  • Ask how many teams have won gold, silver and bronze medals
  • 1≤n≤109,0≤m≤105

Ideas

  • Obviously it is an interval modification, but the number of teams is 1e9, the line segment tree cannot be opened, and the tree array cannot be opened, so use map to maintain the difference array.
  • Then simulate the prefix and operation, the g array stores the number of teams with i
  • Then the for loop runs from m to 1, find the gold, silver and bronze medal lines, and record the number of people before

ac code

#include<bits/stdc++.h>
using namespace std;
#define debug(x) cout<<#x<<"="<<x<<endl
#define ll long long
#define lowbit(x) x&(-x)
#define ls p<<1
#define rs p<<1|1
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
inline int read(){
    int p=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){p=(p<<1)+(p<<3)+(c^48),c=getchar();}
    return f*p;
}
int g[maxn], num[5];
map<int, int> mp;
int main(){
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; i ++){
		int x, y;
		scanf("%d%d", &x, &y);
		mp[x] ++; mp[y + 1] --; //差分操作
	}
	int last = 0, s = 0;
	for(auto it : mp){
		g[s] += it.first - last; //差值表示同分数的队伍个数
		last = it.first; //表示上一个队伍的编号
		s += it.second; //模拟前缀和,表示当前队伍的分数
	}
	vector<int> v; v.resize(5); //存放金银铜牌线之前的所有队伍数量
    //金银铜牌线
	num[1] = ceil(n * 1.0 / 10); 
	num[2] = ceil(n * 1.0 / 4);
	num[3] = ceil(n * 1.0 / 2);
    //分数从高到低跑
	for(int i = m; i >= 1; i --){
		for(int j = 1; j <= 3; j ++){
			if(num[j]){ //没到线
				num[j] = max(0, num[j] - g[i]);
				v[j] += g[i]; //加上该分的人数
			}
		}
	}
	for(int i = 1; i <= 3; i ++){ //由于银牌人数是银牌线以上,金牌线以下的,所以需要减去金牌线的人数,铜牌同理
		if(i == 1) cout << v[i];
		else cout << " " << v[i] - v[i - 1];
	}
	cout << endl;
	return 0;
}

 

Guess you like

Origin blog.csdn.net/weixin_43911947/article/details/113619930