題目鏈接:jzoj 6660 / luogu 4087
題目
最初,農夫約翰的每頭奶牛每天生產加侖的牛奶。由於隨着時間的推移,奶牛的產奶量可能會發生變化,農夫約翰決定定期對奶牛的產奶量進行測量,並將其記錄在日誌中。
他的日誌中的記錄如下:
第一個條目表明:在第天,號奶牛的產奶量比上次測量時降低了加侖。
第二個條目表明:在第天,號奶牛的產奶量比上次測量時增加了加侖。
農夫約翰只有在任何一天內做最多一次測量的時間(即每天最多做一次測量,但可能不做)。不幸的是,約翰有點雜亂無章,他不一定按照時間順序記下測量結果。爲了保持奶牛的產奶動力,農夫約翰自豪地在穀倉的牆上展示了目前產奶量最高的奶牛的照片(如果有若干頭奶牛的產奶量最高,他就會展示所有的圖片)。
請求出約翰需要調整所展示的照片的次數。
請注意,農夫約翰有一大羣奶牛。所以儘管日誌中記錄了一些奶牛改變了產奶量,但仍然還有很多奶牛的產奶量保持在加侖。
輸入
第一行是兩個整數和,分別表示測量的次數和初始產奶量。
接下來行,每行爲一次測量。每行三個數:分別表示日期一(在整數範圍內),奶牛的編號(在整數範圍內),該奶牛的產奶量變化值(一個非負數)。無論如何,每頭奶牛的產奶量永遠保證在範圍
內。
輸出
請輸出約翰總共調整所展示的照片的次數。
樣例輸入
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;
}