西西打pk 解题报告

简要题意

给定 \(n\) 个三元组 \((a_i,b_i,c_i)\),值域为 \([1,m]\)。询问在值域内有多少三元组 \((A,B,C)\) ,满足 \(\exists_{i \in [1,n]} (A > a_i) \lor (B > b_i) \lor (C > c_i)\)

数据范围:\(n \le 10^5,m \le 10^5\)

分析

限制太弱了,考虑求不合法的数量。“三个元素都小于一个三元组“这个限制很强,很好统计。

于是题目转化为一个三维偏序问题。注意到偏序条件都是一段前缀,于是考虑第一位排序后,用第二位为下标的数据结构维护第三位可以取得的最大值。

代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define Inf (1ll<<60)
#define For(i,s,t) for(int i=s;i<=t;++i)
#define Down(i,s,t) for(int i=s;i>=t;--i)
#define ls (i<<1)
#define rs (i<<1|1)
#define bmod(x) ((x)>=mod?(x)-mod:(x))
#define lowbit(x) ((x)&(-(x)))
#define End {printf("NO\n");exit(0);}
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
inline void ckmx(int &x,int y){x=(x>y)?x:y;}
inline void ckmn(int &x,int y){x=(x<y)?x:y;}
inline void ckmx(ll &x,ll y){x=(x>y)?x:y;}
inline void ckmn(ll &x,ll y){x=(x<y)?x:y;}
inline int min(int x,int y){return x<y?x:y;}
inline int max(int x,int y){return x>y?x:y;}
inline ll min(ll x,ll y){return x<y?x:y;}
inline ll max(ll x,ll y){return x>y?x:y;}
inline int read(){
    register int x=0,f=1;
    char c=getchar();
    while(c<'0' || '9'<c) f=(c=='-')?-1:1,c=getchar();
    while('0'<=c && c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();
    return x*f;
}
void write(int x){
    if(x>=10) write(x/10);
    putchar(x%10+'0');
}
const int N=2e5+100;
int n,m;
ll ans;
struct Node{int x,y,z;}a[N];
bool cmp(Node x,Node y){return x.x>y.x;}
struct Tree{int l,r,mn,tag;ll val;}t[N<<2];
void push_up(int i){
    t[i].val=t[ls].val+t[rs].val;
    t[i].mn=min(t[ls].mn,t[rs].mn);
}
void upd(int i,int x){
    t[i].val=1ll*(t[i].r-t[i].l+1)*x;
    t[i].mn=t[i].tag=x;
}
void push_down(int i){
    if(t[i].tag)
        upd(ls,t[i].tag),upd(rs,t[i].tag),t[i].tag=0;
}
void build(int i,int l,int r){
    t[i].l=l,t[i].r=r,t[i].tag=0;
    if(l==r){
        t[i].mn=t[i].val=0;
        return;
    }
    int mid=l+r>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    push_up(i);
}
void update(int i,int l,int r,int x){
    if(l<=t[i].l && t[i].r<=r){
        upd(i,x);
        return;
    }
    push_down(i);
    int mid=t[i].l+t[i].r>>1;
    if(l<=mid) update(ls,l,r,x);
    if(mid<r) update(rs,l,r,x);
    push_up(i);
}
int query(int i,int l,int r,int x){
    if(t[i].mn>x) return -1;
    if(t[i].l==t[i].r) return t[i].l;
    push_down(i);
    int mid=t[i].l+t[i].r>>1;
    if(l<=t[i].l && t[i].r<=r)
        return t[ls].mn<=x ? query(ls,l,r,x) :query(rs,l,r,x);
    int res;
    if(l<=mid && (res=query(ls,l,r,x))!=-1) return res;
    return query(rs,l,r,x);
}
int main()
{
#if !ONLINE_JUDGE
    freopen("pk.in","r",stdin);
    freopen("pk.out","w",stdout);
#endif 
    while(true){
        n=read(),m=read();
        if(!n && !m) return 0;
        For(i,1,n) a[i].x=read(),a[i].y=read(),a[i].z=read();
        sort(a+1,a+n+1,cmp);
        ans=1ll*m*m*m;
        int ind=1;
        build(1,1,m);
        Down(i,m,1){
            while(ind<=n && a[ind].x==i){
                int pos=query(1,1,a[ind].y,a[ind].z);
                if(pos!=-1)
                    update(1,pos,a[ind].y,a[ind].z);
                ++ind;
            }
            ans-=t[1].val;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2025-09-18 13:38  XiaoZi_qwq  阅读(4)  评论(0)    收藏  举报