题解:本质是维护双向链表,但要注意处理边界值,在处理过程中始终保证左右端点不越界,优先处理左边的水滴即可完成题目中的在有多个水滴要爆时先处理左边。
#pragma GCC optimize(2, 3, "Ofast", "inline")
#include <bits/stdc++.h>
using namespace std;
class Gezi
{
public:
int pos,w;
int l,r;
};
vector<Gezi> a;//当前剩余的有水滴的数组;
unordered_map<int,int> index1;//有水滴的格子在数组中的位置;
bool compare(Gezi g1,Gezi g2)
{
return g1.pos<g2.pos;
}
void work()
{
int c,m,n;
cin>>c>>m>>n;
for(int i=1;i<=m;i++)
{
int x,w;
cin>>x>>w;
Gezi gezi1;
gezi1.pos=x;
gezi1.w=w;
a.push_back(gezi1);
}
sort(a.begin(),a.end(),compare);
for(int i=0;i<m;i++)
{
index1[a[i].pos]=i;
a[i].l=i-1;
a[i].r=i+1;
}
int num=m;
for(int NUM_ORDER=0;NUM_ORDER<n;NUM_ORDER++)
{
int p;
cin>>p;
int pos=index1[p];
a[pos].w++;
int l=pos,r=a[pos].r;
while(1)
{
//处理当前水滴 靠左边的水滴(题目要求处理左边的格子),注意判断边界
while(l>=0&&a[l].w>=5)
{
a[l].w=0;
num--;
if(r<a.size()) a[r].w++;
//更新目前观察水滴为其左边的位置
l=a[l].l;
//维护双向链表
if(r<a.size()) a[r].l=l;
if(l>=0) a[l].r=r;
//左水滴数量增加
if(l>=0) a[l].w++;
}
//上述处理完之后左边应该已经没有要爆开的格子,右边格子也要爆开,处理当前右边格子的左右格子,并继续处理其所有的左边格子
if(r<a.size()&&a[r].w>=5)
{
a[r].w=0;
num--;
if(l>=0) a[l].w++;
r=a[r].r;
if(r<a.size()) a[r].l=l;
if(l>=0) a[l].r=r;
if(r<a.size()) a[r].w++;
}
else
{
break;
}
}
if(l>=0) a[l].r=r;
if(r<a.size()) a[r].l=l;
cout<<num<<endl;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
work();
return 0;
}