P4849 寻找宝藏

很明显是个四维偏序的 LIS。

两层 cdq 处理四维偏序。按 \(a\) 排序。第一层 cdq 按 \(b\) 排序,打上标记 0/1 表示该元素按 \(a\) 排序后是在左/右半区间。第二层 cdq 就是正常的 cdq 但是只有标记为 0 的元素更新标记为 1 的元素。同理可以继续嵌套处理更高维的偏序关系。

用左半区间更新右半区间,所以尽量优先更新左半区间。LIS 和方案数的 dp 是简单的。

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#define fin(x) freopen(#x".in","r",stdin)
#define fout(x) freopen(#x".out","w",stdout)
#define fr(x) fin(x),fout(x);
#define Fr(x,y) fin(x),fout(y)
#define INPUT(_1,_2,FILE,...) FILE
#define IO(...) INPUT(__VA_ARGS__,Fr,fr)(__VA_ARGS__)
using namespace std;
using namespace __gnu_pbds;
#define mp make_pair
#define pii pair<ll,ll>
#define fi first
#define se second
#define pb push_back
#define cfast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define ll long long
#define ull unsigned long long
#define intz(x,y) memset((x),(y),sizeof((x)))
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
#define tup(x) array<int,(x)>
inline ll read(){
    ll x=0,f=1;char ch=nc();
    while(ch<48||ch>57){if(ch=='-')f=-1;ch=nc();}
    while(ch>=48&&ch<=57)x=x*10+ch-48,ch=nc();
   	return x*f;
}
//void write(int x){cout<<x<<' ';}
//void write(pii x){cout<<"P("<<x.fi<<','<<x.se<<")\n";}
//void write(vector<auto>x){for(auto i:x)write(i);cout<<'\n';}
//void write(auto *a,int l,int r){for(int i=l;i<=r;i++)write(a[i]);cout<<'\n';}
inline ll lowbit(ll x){return x&-x;}
#define pcount(x) __builtin_popcount(x)
inline void cmx(ll &x,ll y){if(y>x)x=y;}
inline void cmn(ll &x,ll y){if(y<x)x=y;}
const int mod=998244353;
ll qp(ll x,int y){ll res=1;for(;y;x=x*x%mod,y>>=1)if(y&1)res=res*x%mod;return res;}
const int N=80005;
int tot,n,m,p[N],T;ll f[N],g[N];
struct node{int a,b,c,d,id;ll v;bool fl;}a[N],b[N],c[N];
bool chk(node x,node y){return (x.a==y.a&&x.b==y.b&&x.c==y.c&&x.d==y.d);}
bool cmp(node x,node y){return x.a^y.a?x.a<y.a:(x.b^y.b?x.b<y.b:(x.c^y.c?x.c<y.c:x.d<y.d));}
bool cmp1(node x,node y){return x.b^y.b?x.b<y.b:(x.a^y.a?x.a<y.a:(x.c^y.c?x.c<y.c:x.d<y.d));}
bool cmp2(node x,node y){return x.c^y.c?x.c<y.c:x.d<y.d;}
ll t[N],tg[N];
inline void upd(int x,ll d,ll y){
	for(;x<=T;x+=lowbit(x))
		if(d>t[x])t[x]=d,tg[x]=y;
		else if(d==t[x])(tg[x]+=y)%=mod;
}
inline void clr(int x){for(;x<=T;x+=lowbit(x))t[x]=tg[x]=0;}
inline pii query(int x){
	ll res=0,rg=0;
	for(;x;x-=lowbit(x))
		if(t[x]>res)res=t[x],rg=tg[x];
		else if(t[x]==res)(rg+=tg[x])%=mod;
	return mp(res,rg);
}
void cdq1(int L,int R){
	if(L==R)return;int mid=L+R>>1;
	cdq1(L,mid);
	for(int i=L;i<=R;i++)c[i]=b[i];vector<int>w;
	sort(c+L,c+1+mid,cmp2),sort(c+mid+1,c+1+R,cmp2);
	for(int l=L,r=mid+1;r<=R;r++)if(!c[r].fl){
		while(l<=mid&&c[l].c<=c[r].c)
			(c[l].fl?(upd(c[l].d,f[c[l].id],g[c[l].id]),w.pb(c[l].d),1):0),++l;
		pii res=query(c[r].d);res.fi+=c[r].v;
		if(res.fi>f[c[r].id])f[c[r].id]=res.fi,g[c[r].id]=res.se;
		else if(res.fi==f[c[r].id])(g[c[r].id]+=res.se)%=mod;
	}
	for(int i:w)clr(i);w.shrink_to_fit();
	cdq1(mid+1,R);
}
void cdq(int L,int R){
	if(L==R)return;int mid=L+R>>1;
	cdq(L,mid);
	for(int i=L;i<=mid;i++)b[i]=a[i],b[i].fl=1;
	for(int i=mid+1;i<=R;i++)b[i]=a[i],b[i].fl=0;
	sort(b+L,b+1+R,cmp1),cdq1(L,R);
	cdq(mid+1,R);
}
inline void UesugiErii(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>a[i].a>>a[i].b>>a[i].c>>a[i].d>>a[i].v,p[++T]=a[i].d;
	sort(p+1,p+1+T);T=unique(p+1,p+1+T)-p-1;
	for(int i=1;i<=n;i++)
		a[i].d=lower_bound(p+1,p+1+T,a[i].d)-p;
	sort(a+1,a+1+n,cmp);
	for(int i=n;i>=1;i--)
		if(chk(a[i],a[i-1]))
			a[i-1].v+=a[i].v;
		else b[++tot]=a[i];
	swap(a,b),n=tot;
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++)a[i].id=i,f[i]=a[i].v,g[i]=1;
	cdq(1,n);ll mx=0,ans=0;
	for(int i=1;i<=n;i++)
		if(f[i]>mx)mx=f[i],ans=g[i];
		else if(f[i]==mx)(ans+=g[i])%=mod;
	cout<<mx<<'\n'<<ans;
}
signed main(){
	//IO();
	cfast;
	int _=1;//cin>>_;
	for(;_;_--)UesugiErii();
	return 0;
}
posted @ 2025-12-03 07:59  Uesugi1  阅读(2)  评论(0)    收藏  举报