这题虽然说是模板题,但是确实有很多地方第一次学有点难懂。
先看一下树状数组的介绍:
https://blog.csdn.net/flushhip/article/details/79165701
https://www.cnblogs.com/George1994/p/7710886.html
本题参考博客:
https://blog.csdn.net/a664607530/article/details/78596724
看完之后我来介绍几个晦涩点:
(1)
这个操作和常规的很多二分搜索的正好相反。
而且这一题是肯定找得到答案的。
(2)
既然是离散化,就要把每个点的初始状态都表示出来。
这个是对每一次操作过后的状态的动态变化都记录下来了,而不是在对应点对应的数组位置上去修改!!!这是个对离散化操作的晦涩点。
(3)
意思是树状数组bit[ ]的初始化,这里是按照id由小到大来排序的。
(4)
之所以要先-1再+1是因为要将原来的状态先删除再加入新的状态(实质上就是更新区段数值),原状态一定要删除,因为这个状态以后都不会存在了。
(5)
数组的大小不要开错。
代码:
//E
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXN=1e5+10;
struct Node
{
int id,ac,pe;
Node(){}
Node(int a,int b,int c): id(a),ac(b),pe(c){}
friend bool operator <(Node a,Node b)
{
if(a.ac!=b.ac)
return a.ac>b.ac;
else if(a.pe!=b.pe)
return a.pe<b.pe;
else
return a.id<b.id;
}
}pos,state[MAXN*2];//记录离散化以后的每一步的状态
int t[MAXN],p[MAXN];
int bit[MAXN*2];//树状数组
int AC[MAXN],T[MAXN];//记录每一个成员的AC数量和罚时
int n,m;
int Locate(Node temp)
{
int l=1,r=n+m,mid;
while(l<=r)
{
mid=(l+r)/2;
if(state[mid].ac<temp.ac) r=mid-1;
else if(state[mid].ac>temp.ac) l=mid+1;
else if(state[mid].pe<temp.pe) l=mid+1;
else if(state[mid].pe>temp.pe) r=mid-1;
else if(state[mid].id<temp.id) l=mid+1;
else if(state[mid].id>temp.id) r=mid-1;
else return mid;
}
return mid;
}
int lowbit(int k)
{
return k&(k^(k-1));
}
void Update(int id,int val)
{
int i;
for(i=id;i<=n+m;i+=lowbit(i))
bit[i]+=val;
}
int Query(int id)
{
int i;
int ans=0;
for(i=id;i>0;i-=lowbit(i))
ans+=bit[i];
return ans;
}
int main()
{
int i;
int id;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(state,0,sizeof(state));
for(i=1;i<=n;i++)//表示最初始的状态
state[i]=Node(i,0,0);
memset(t,0,sizeof(t));
memset(p,0,sizeof(p));
memset(AC,0,sizeof(AC));
memset(T,0,sizeof(T));
for(i=1;i<=m;i++)
{
scanf("%d%d",&t[i],&p[i]);
AC[t[i]]++;
T[t[i]]+=p[i];
state[n+i]=Node(t[i],AC[t[i]],T[t[i]]);
}
sort(state+1,state+1+n+m);
memset(bit,0,sizeof(bit));
for(i=1;i<=n;i++)
{
pos=Node(i,0,0);
id=Locate(pos);
Update(id,1);//将初始化的排名按照id大小排序(开始大家的AC和罚时都是0)
}
memset(AC,0,sizeof(AC));
memset(T,0,sizeof(T));
for(i=1;i<=m;i++)
{
pos=Node(t[i],AC[t[i]],T[t[i]]);
id=Locate(pos);
Update(id,-1);
AC[t[i]]++;
T[t[i]]+=p[i];
pos=Node(t[i],AC[t[i]],T[t[i]]);
id=Locate(pos);
Update(id,1);
pos=Node(1,AC[1],T[1]);
id=Locate(pos);
printf("%d\n",Query(id));
}
}
return 0;
}