每日一题--糖糖别胡说,我真的不是签到题目(线段树 or 差分)

题目链接

题意:

这题我线段树写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();
}
发布了536 篇原创文章 · 获赞 71 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/105688700