qwq校内模拟赛的
贼自闭。
首先,我们来考虑如何更新一个点的
一个比较 的想法就是我们对于每个点记录以他为开头的的 长度。
如果我们选择用这个位置之后的所有位置的 值+1来更新的话,貌似无法判断这个 值对应的高度是不是合法的。
而我们如果选择用高度大于这个点的 来更新的话,又无法处理位置的问题。
但是我们会发现数据范围中,每次加入一棵树的高度和砍掉一个树的位置的范围是[1,10]$,是不是可以从这里下手呢?
首先我们定义 表示高度是 的位置是哪个, 表示第 个位置的高度是多少。
然后根据上面的思路,我们不难发现,我们肯定是要建两颗线段树的,一颗以位置以下标,一颗是高度为下标,权值都是 值。
首先考虑插入操作,对于每次插入,实际上我们只会修改不超过十个位置的 值,我们将 到 所有高度对应的位置都清零,我们会发现,如果倒着做的话,我们可以直接对于每个点,用其位置之后的 值+1来更新了,因为小于这个高度的数 值都是 ,不会产生贡献
那么删除是不是也就同理啦?我们一次最多修改 个位置,会发现可以直接用高度大于该位置的来更新,因为位置在这个位置前面的并不会产生贡献。
对于那个整体+的操作,每次只需要维护一个 ,对读入的 , ,每次 就ok
需要注意的是,我们对于删除,一定要把这个点所有的相关信息都清空。
qwq
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define mk make_pair
#define pb push_back
#define ll long long
#include<set>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 2e6+1e2;
struct tree{
int f[maxn];
void up(int root)
{
f[root]=max(f[2*root],f[2*root+1]);
}
void update(int root,int l,int r,int x,int y)
{
if (l==r)
{
f[root]=y;
return;
}
int mid = l+r >> 1;
if (x<=mid) update(2*root,l,mid,x,y);
else update(2*root+1,mid+1,r,x,y);
up(root);
}
int query(int root,int l,int r,int x,int y)
{
if (x<=l && r<=y) return f[root];
int mid = l+r >> 1;
int ans=0;
if (x<=mid) ans=max(ans,query(2*root,l,mid,x,y));
if (y>mid) ans=max(ans,query(2*root+1,mid+1,r,x,y));
return ans;
}
};
tree f,g;
//f is position
//g is height
int n;
int delta = 2e5;
int q;
int pos[maxn];
int height[maxn];
set<int> s;
int a[maxn];
int main()
{
n=read();q=read();
int m=delta+10010;
for (int i=1;i<=q;i++)
{
int opt=read();
if (opt==1)
{
int p=read(),h=read()+delta;
s.insert(p);
pos[h]=p;
height[p]=h;
for(int i=h;i>=h-9;i--)
{
if (!pos[i]) continue;
int now = pos[i];
f.update(1,1,n,now,0);
g.update(1,1,m,i,0);
}
for (int i=h;i>=h-9;i--)
{
if (!pos[i]) continue;
int now = f.query(1,1,n,pos[i]+1,n)+1; //找位置在这个点后面的
f.update(1,1,n,pos[i],now);
g.update(1,1,m,i,now);
}
}
else
{
int k=read();
set<int>::iterator it = s.begin();
int cnt=0;
while (cnt<k) a[++cnt]=*it,++it;
--it;
s.erase(it);
for (int i=1;i<=cnt;i++)
{
if (!height[a[i]]) continue;
f.update(1,1,n,a[i],0);
g.update(1,1,m,height[a[i]],0);
}
for (int i=cnt-1;i>=1;i--)
{
if (!height[a[i]]) continue;
int now = g.query(1,1,m,height[a[i]]+1,m)+1;//找高度大的。
f.update(1,1,n,a[i],now);
g.update(1,1,m,height[a[i]],now);
}
pos[height[a[cnt]]]=0;
height[a[cnt]]=0;
}
cout<<f.f[1]<<"\n";
delta--;
}
return 0;
}