Milk Measurement

Milk MeasurementMilk\ Measurement

題目鏈接:jzoj 6660 / luogu 4087

題目

最初,農夫約翰的每頭奶牛每天生產GG加侖的牛奶(1G109)(1≤G≤10^9)。由於隨着時間的推移,奶牛的產奶量可能會發生變化,農夫約翰決定定期對奶牛的產奶量進行測量,並將其記錄在日誌中。
他的日誌中的記錄如下:
35 1234 235\ 1234\ -2
14 2345 +314\ 2345\ +3
第一個條目表明:在第3535天,12341234號奶牛的產奶量比上次測量時降低了22加侖。
第二個條目表明:在第1414天,23452345號奶牛的產奶量比上次測量時增加了33加侖。
農夫約翰只有在任何一天內做最多一次測量的時間(即每天最多做一次測量,但可能不做)。不幸的是,約翰有點雜亂無章,他不一定按照時間順序記下測量結果。爲了保持奶牛的產奶動力,農夫約翰自豪地在穀倉的牆上展示了目前產奶量最高的奶牛的照片(如果有若干頭奶牛的產奶量最高,他就會展示所有的圖片)。

請求出約翰需要調整所展示的照片的次數。

請注意,農夫約翰有一大羣奶牛。所以儘管日誌中記錄了一些奶牛改變了產奶量,但仍然還有很多奶牛的產奶量保持在GG加侖。

輸入

第一行是兩個整數NNGG,分別表示測量的次數和初始產奶量。
接下來NN行,每行爲一次測量。每行三個數:分別表示日期一(在整數1...1061...10^6範圍內),奶牛的編號(在整數1...1091...10^9範圍內),該奶牛的產奶量變化值(一個非負數)。無論如何,每頭奶牛的產奶量永遠保證在0...1090...10^9範圍
內。

輸出

請輸出約翰總共調整所展示的照片的次數。

樣例輸入

4 10
7 3 +3
4 2 -1
9 3 -1
1 1 +2

樣例輸出

3

思路

這道題可以用線段樹做,但是我用的是模擬。
就是維護第一大和第二大(這樣才能省時間),具體怎麼搞看代碼吧。
(代碼中的找新的第二名就是直接暴力找)

代碼

#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

struct node {
	int day, num, add;
}a[1000001];
int n, G, cnt = 100, cow[1000001], maxn, maxx, sec, sex, ans;
map<int, int>mapp;

bool cmp(node x, node y) {
	return x.day < y.day;
}

void findsec() {//暴力找到第二名
	sec = -2147483647;
	sex = 0;
	for (int j = 1; j <= cnt; j++) {
		if (cow[j] != maxn && cow[j] > sec) {
			sec = cow[j];
			sex = 1;
		}
		else if (cow[j] == sec) sex++;
	}
}

int main() {
//	freopen("measurement.in", "r", stdin);
//	freopen("measurement.out", "w", stdout);
	
	scanf("%d %d", &n, &G);//讀入
	for (int i = 1; i <= n; i++) {
		scanf("%d %d %d", &a[i].day, &a[i].num, &a[i].add);//讀入
	}
	
	sort(a + 1, a + n + 1, cmp);//按時間排序
	
	for (int i = 1; i <= n; i++) {
		if (!mapp[a[i].num]) mapp[a[i].num] = ++cnt;//離散化
		if (cow[mapp[a[i].num]] == maxn) {//原來是最大
			cow[mapp[a[i].num]] += a[i].add;//數量改變
			if (a[i].add > 0) {//產奶量增加
				if (maxx != 1) {//原來第一名不止一個
					sec = maxn;
					sex = maxx - 1;
					maxx = 1;
					ans++;
				}
				maxn = cow[mapp[a[i].num]];
			}
			else {//產奶量減少
				if (maxx != 1) {//原來第一名不止一個
					maxx--;
					ans++;
					if (cow[mapp[a[i].num]] > sec) {//還比原來的第一名大
						sec = cow[mapp[a[i].num]];
						sex = 1;
					}
					else if (cow[mapp[a[i].num]] == sec) sex++;//跟原來的第二名一樣大
				}
				else {//原來第一名只有一個
					if(cow[mapp[a[i].num]] > sec) maxn = cow[mapp[a[i].num]];//還是比第二名高
						else if(cow[mapp[a[i].num]] == sec) {//跟第二名一樣高(第二名變成了第一名,要重新找第二名)
							maxn = sec;
							maxx = sex + 1;
							findsec();
							ans++;
						}
						else {//比第二名低
							maxn = sec;
							maxx = sex;
							findsec();
							ans++;
						}
				}
			}
		}
		else if (cow[mapp[a[i].num]] == sec) {//原來是第二名
			cow[mapp[a[i].num]] += a[i].add;//加h值
			if(a[i].add < 0) {//產量減少
				sex--;
				if(!sex) findsec();//要重新去找第二名
			}
			else {//產量增加
				if (cow[mapp[a[i].num]] == maxn) {//現在跟第一名一樣多
					sex--;
					maxx++;
					ans++;
					if (!sex) findsec();
				}
				else if (cow[mapp[a[i].num]] > maxn) {//超過了第一名
					sec = cow[mapp[a[i].num]];
					sex = 1;
					swap(maxn, sec);
					swap(maxx, sex);
					ans++;
				}
				else {//沒有超過第一名(那肯定是第二名)
					sec = cow[mapp[a[i].num]];
					sex = 1;
				}
			}
		}
		else {//原來不是第一也不是第二
			cow[mapp[a[i].num]] += a[i].add;//加值
			if (cow[mapp[a[i].num]] == maxn) {//已經是和第一同樣大了 
				maxx++;
				ans++;
			}
			else if (cow[mapp[a[i].num]] == sec) {//已經和第二同樣大了
				sex++;
			}
			else if (cow[mapp[a[i].num]] > maxn) {//已經是最大的了
				sec = cow[mapp[a[i].num]];
				sex = 1;
				swap(maxn, sec);
				swap(maxx, sex);
				ans++;
			}
			else if (cow[mapp[a[i].num]] > sec){//比第二大,但是比第一小
				sec = cow[mapp[a[i].num]];
				sex = 1;
			}
		}
	}
	
	printf("%d", ans);//輸出
	
//	fclose(stdin);
//	fclose(stdout);
	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章