题意:
这题我线段树写A不了,真的有毒,自己随机造了几百组数据了。。
ps:
(获得出题人的数据后,发现 数据出问题了,
出题人的数据ci有为0的情况,已联系出题人修改数据)
看到别人的做法都是差分求出最后的数值,然后倒着求答案。
今天我就来一个特殊的做法,直接正着模拟。开两棵线段树,维护0和1
① 遇到一个0 需要把种类为1的小于当前bi全部消掉,这里用权值线段树维护区间和+懒人标记 去更新
② 接着将当前这个0插入到0种类的线段树内。最后的答案就是sum[0][1]+sum[1][1]
③ 至于如何维护 施法 前面的数字全部加1呢?用一个基数base代表施法次数。每次遇到新的ai bi 将bi-base就能做到和前面的bi是一个维度的
时间复杂度是n*log(mx(a[i]+m)
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=5e4+10,M=2e6+10;
struct node
{
int ty,w;
}a[N];
int n,m,len;
int w[N],vis[N],l1;
int sum[2][4*M],lazy[2][4*M];
void pushdown(int id,int ty)
{
if(lazy[ty][id]!=0){
lazy[ty][id<<1]=lazy[ty][id];
lazy[ty][id<<1|1]=lazy[ty][id];
sum[ty][id<<1]=0;
sum[ty][id<<1|1]=0;
lazy[ty][id]=0;
}
}
void up(int id,int l,int r,int ql,int qr,int val,int ty)
{
if(ql<=l&&r<=qr){
if(val==-1) lazy[ty][id]=-1,sum[ty][id]=0;
else lazy[ty][id]=0,sum[ty][id]+=1;
return ;
}
pushdown(id,ty);
int mid=l+r>>1;
if(ql<=mid) up(id<<1,l,mid,ql,qr,val,ty);
if(qr>mid) up(id<<1|1,mid+1,r,ql,qr,val,ty);
sum[ty][id]=sum[ty][id<<1]+sum[ty][id<<1|1];
}
void solve()
{
scanf("%d%d",&n,&m);
mem(sum,0);mem(lazy,0);mem(vis,0);
rep(i,1,n) {
scanf("%d%d",&a[i].ty,&a[i].w);
a[i].w+=m;
}
l1=0;
rep(i,1,m) {
int x;scanf("%d",&x);
if(vis[x]==0) w[++l1]=x;
vis[x]++;
}
sort(w+1,w+1+l1);
int base=0;len=1;
for(int i=1;i<=n;++i){
int ww=a[i].w-base;
if(ww>1) up(1,1,M-10,1,ww-1,-1,1-a[i].ty);
up(1,1,M-10,ww,ww,1,a[i].ty);
while(len<=m&&i==w[len]) base+=vis[w[len]],len++;
}
int ans=sum[0][1]+sum[1][1];
printf("%d\n",ans);
}
int main()
{
//freopen("2.in", "r", stdin);
int _;cin>>_;while(_--)
solve();
}
差分做法:
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=5e4+10 ;
struct node
{
int ty,w;
}a[N];
int n,m;
int sum[2][N],w[N];
void solve()
{
scanf("%d%d",&n,&m);
mem(sum,0);
rep(i,1,n) scanf("%d%d",&a[i].ty,&a[i].w);
rep(i,1,m){
int x;
scanf("%d",&x);
sum[0][1]+=1;sum[0][x+1]-=1;
sum[1][1]+=1;sum[1][x+1]-=1;
}
rep(i,1,n){
rep(j,0,1) sum[j][i]+=sum[j][i-1];
w[i]=a[i].w+sum[a[i].ty][i];
}
int mx[2],ans=0;
mx[0]=mx[1]=0;
per(i,n,1){
if(mx[1-a[i].ty]<=w[i]) ans++;
mx[a[i].ty]=max(mx[a[i].ty],w[i]);
}
printf("%d\n",ans);
}
int main()
{
//ios::sync_with_stdio(false);
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int _;cin>>_;while(_--)
solve();
}