首页 > 其他分享 >题解:P10800 「CZOI-R1」卡牌

题解:P10800 「CZOI-R1」卡牌

时间:2024-07-23 15:54:01浏览次数:12  
标签:dots le int 题解 sum 卡牌 CZOI ui max

\(\text{Link}\)

最近做的最神金的一道数据结构题。

题意

给出 \(m\) 个值域为 \([1,n]\) 的四元组 \(t_{i,0\sim 3}\),定义四元组 \(A\) 胜于四元组 \(B\) 当且仅当最多存在一个 \(j\in[0,3]\) 使得 \(A_j\le B_j\),求出有多少个值域为 \([1,n]\) 的四元组 \(A\) 胜于所有的 \(t_{1\sim n}\)。

\(n,m\le 5\times 10^5\)。

题解

为了易读,本文中递增表示不递减,递减表示不递增。

一个直接的思路就是令 \(v_{i,j,k}\) 表示有几个合法四元组前三维分别为 \(i,j,k\),此时合法四元组的第四维是一个后缀。

那么我们考虑一个限制 \(t\):

  • 如果前三维均比 \(t\) 大,则无需考虑该限制;
  • 如果前三维恰有一维不比 \(t\) 大,则第四维要比 \(t\) 大;
  • 如果前三维有至少两维不比 \(t\) 大,则必然不合法。

考虑这个恰有一维是不需要的,我们可以将它转为对 \(v\) 的操作:

  • 对于 \(i\le t_0\),将 \(v_{i,j,k}\) 对 \(n-t_3\) 取 \(\min\);
  • 对于 \(j\le t_1\),将 \(v_{i,j,k}\) 对 \(n-t_3\) 取 \(\min\);
  • 对于 \(k\le t_2\),将 \(v_{i,j,k}\) 对 \(n-t_3\) 取 \(\min\);
  • 对于 \(i\le t_0\land j\le t_1\),将 \(v_{i,j,k}\) 设为 \(0\);
  • 对于 \(i\le t_0\land k\le t_2\),将 \(v_{i,j,k}\) 设为 \(0\);
  • 对于 \(j\le t_1\land k\le t_2\),将 \(v_{i,j,k}\) 设为 \(0\)。

显然这些操作的顺序对答案无影响,则我们可以处理出 \(a_i,b_j,c_k\) 表示考虑前三种操作后第 \(i\) 行,第 \(j\) 列,第 \(k\) 层的取 \(\min\) 标记。不考虑置零操作,则 \(v_{i,j,k}=\min(a_i,b_j,c_k)\),其中 \(a,b,c\) 均单调递增。

再考虑置零操作。设第 \(j\) 列最大清到行 \(u_j\)(第一种),第 \(k\) 层最大清到行 \(x_k\)(第二种)、列 \(y_k\)(第三种),其中 \(u,x,y\) 均单调递减。

答案即可表示为

\[\sum_{i,j,k}^{i>u_j\land i>x_k\land j>y_k}\min(a_i,b_j,c_k) \]

但这样不优。

令 \(f_j\) 为最大的 \(i\) 使得 \(a_i\le b_j\),\(g_k\) 为最大的 \(j\) 使得 \(b_j\le c_k\),\(h_k\) 为最大的 \(i\) 使得 \(a_i\le c_k\),显然 \(f,g,h\) 均单调递增。

考虑对 \(k\) 扫描线,则第 \(k\) 层的 \(v_{i,j,k}\) 如下所示:

\[\begin{pmatrix} b_1&b_2&\dots&b_{j}&c_k&\dots&c_k\\ .&.&\dots &.&.&\dots&.\\ b_1&b_2&\dots&b_{j}&c_k&\dots&c_k\\ b_1&b_2&\dots&b_{j}&a_{h_k}&\dots&a_{h_k}\\ .&.&\dots &.&.&\dots&.\\ b_1&b_2&\dots &b_j&a_{f_j+1}&\dots&a_{f_j+1}\\ b_1&b_2&\dots &a_{f_j}&a_{f_j}&\dots&a_{f_j}\\ .&.&\dots &.&.&\dots&.\\ b_1&a_{f_2}&\dots &a_{f_2}&a_{f_2}&\dots&a_{f_2}\\ .&.&\dots &.&.&\dots&.\\ .&.&\dots &.&.&\dots&.\\ a_{1}&a_{1}&\dots &a_{1}&a_{1}&\dots&a_{1}\\ \end{pmatrix} \]

其中 \(j=g_k\)。则答案分为四个部分:

  • 在 \(g_k\) 列及之前的取到 \(a_i\) 作为最小值的部分:\(\displaystyle\sum_{j=y_k+1}^{g_k}\sum_{i=\max(x_k,u_j)+1}^{f_j}a_i\);
  • 取到 \(b_j\) 作为最小值的部分:\(\displaystyle\sum_{j=y_k+1}^{g_k}[n-\max(x_k,u_j,f_j)]b_j\);
  • 在 \(g_k\) 列之后的取到 \(a_i\) 作为最小值的部分:\(\displaystyle\sum_{j=g_k+1}^{n}\sum_{i=\max(x_k,u_j)+1}^{h_k}a_i\);
  • 取到 \(c_k\) 作为最小值的部分:\(\displaystyle c_k\sum_{j=g_k+1}^{n}[n-\max(x_k,u_j,h_k)]\)。

再求出 \(p_i\) 为最大的 \(j\) 使得 \(u_j\ge i\),\(q_i\) 为最小的 \(j\) 使得 \(f_j\ge i\)。在移动 \(k\to k+1\) 时增加 \(h\)、减少 \(x\) 并依据式子对四个部分分别增量,分别使用线段树或树状数组维护即可。

认为 \(n,m\) 同阶,时间复杂度 \(O(n\log n)\)。

参考代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ui unsigned
namespace IO{//by cyffff
	
}
inline void umn(int &x,int y){ x=min(x,y); }
inline void umx(int &x,int y){ x=max(x,y); }
const int N=5e5+10;
int n,m,a[N],b[N],c[N],f[N],g[N],h[N],u[N],x[N],y[N],p[N],q[N];
struct Segment_Tree{
	#define ls (rt<<1)
	#define rs (rt<<1|1)
	ui ans[N<<2],sum[N<<2],tag[N<<2];
	inline void pushup(int rt){
		ans[rt]=ans[ls]+ans[rs];
		sum[rt]=sum[ls]+sum[rs];
	}
	inline void pushtag(int rt,ui v){
		tag[rt]+=v,ans[rt]+=sum[rt]*v;
	}
	inline void pushdown(int rt){
		if(!tag[rt]) return ;
		pushtag(ls,tag[rt]);
		pushtag(rs,tag[rt]);
		tag[rt]=0;
	}
	inline void build(int rt,int l,int r){
		if(l==r){
			sum[rt]=b[l];
			return ;
		}
		int mid=l+r>>1;
		build(ls,l,mid),build(rs,mid+1,r);
		pushup(rt);
	}
	inline void modify(int rt,int l,int r,int L,int R,ui v){
		if(L>R) return ;
		if(L<=l&&r<=R) return pushtag(rt,v);
		pushdown(rt);
		int mid=l+r>>1;
		if(L<=mid) modify(ls,l,mid,L,R,v);
		if(R>mid) modify(rs,mid+1,r,L,R,v);
		pushup(rt);
	}
	inline ui query(int rt,int l,int r,int L,int R){
		if(L>R) return 0;
		if(L<=l&&r<=R) return ans[rt];
		pushdown(rt);
		int mid=l+r>>1;
		ui s=0;
		if(L<=mid) s+=query(ls,l,mid,L,R);
		if(R>mid) s+=query(rs,mid+1,r,L,R);
		return s;
	}
}T3;
struct BIT{
	#define lowbit(i) (i&-i)
	ui t1[N],t2[N];
	inline void add(int x,ui v){
		for(int i=x;i<=n;i+=lowbit(i))
			t1[i]+=v,t2[i]+=1u*x*v;
	}
	inline ui query(int x){
		ui s1=0,s2=0;
		for(int i=x;i;i-=lowbit(i))
			s1+=t1[i],s2+=t2[i];
		return 1u*(x+1)*s1-s2; 
	}
	inline ui query(int l,int r){
		return l<=r?query(r)-query(l-1):0;
	}
}T[3];
int main(){
	n=read(),m=read();
	for(int i=1;i<=n+1;i++)
		a[i]=b[i]=c[i]=n;
	for(int i=1;i<=m;i++){
		int A=read(),B=read(),C=read(),D=read();
		umn(a[A],n-D),umn(b[B],n-D),umn(c[C],n-D);
		umx(u[B],A),umx(x[C],A),umx(y[C],B);
	}
	for(int i=n;i;i--)
		umn(a[i],a[i+1]),umn(b[i],b[i+1]),umn(c[i],c[i+1]),
		umx(u[i],u[i+1]),umx(x[i],x[i+1]),umx(y[i],y[i+1]);
	x[0]=n;
	for(int i=0,j=1;j<=n;j++){
		while(i<n&&a[i+1]<=b[j]) i++;
		f[j]=i;
	}
	for(int j=0,k=1;k<=n;k++){
		while(j<n&&b[j+1]<=c[k]) j++;
		g[k]=j;
	}
	for(int i=0,k=1;k<=n;k++){
		while(i<n&&a[i+1]<=c[k]) i++;
		h[k]=i;
	}
	for(int j=0,k=n;k;k--){
		while(j<n&&u[j+1]>=k) j++;
		p[k]=j;
	}
	for(int j=n+1,k=n;k;k--){
		while(j&&f[j-1]>=k) j--;
		q[k]=j;
	}
	T3.build(1,1,n);
	ui ans=0;
	for(int k=1;k<=n;k++){
		for(int i=h[k-1]+1;i<=h[k];i++)
			if(i>x[k-1]){
				T[1].add(p[i]+1,a[i]);
				T[2].add(p[i]+1,-1);
			}
		for(int i=x[k-1];i>x[k];i--){
			T[0].add(max(p[i]+1,q[i]),a[i]);
			T3.modify(1,1,n,p[i]+1,q[i]-1,1);
			if(i<=h[k]) T[1].add(p[i]+1,a[i]);
			if(i>h[k]) T[2].add(p[i]+1,1);
		}
		ans+=T[0].query(y[k]+1,g[k]);
		ans+=T3.query(1,1,n,y[k]+1,g[k]);
		ans+=T[1].query(max(y[k],g[k])+1,n);
		ans+=1u*c[k]*T[2].query(max(y[k],g[k])+1,n);
	}
	write(ans);
	flush();
}

标签:dots,le,int,题解,sum,卡牌,CZOI,ui,max
From: https://www.cnblogs.com/cyffff/p/18318608

相关文章

  • 题解:P10717「KDOI-05」简单的树上问题
    \(\text{Link}\)题意给你一颗\(n\)个结点的树,有\(k\)次操作,第\(i\)次操作:每个点初始都处于未激活状态;以\(p_{i,j}\)的概率激活点\(j\);对于每个未激活的点\(i\),如果存在激活的结点\(j,k\)且\(i\)在\(j\)到\(k\)的路径上,则\(i\)也会被激活。给出\(v_{i......
  • NOI2024 题解
    D2T3树形图首先判掉一些case将任意一个\(1\)类点定为根,求出一棵dfs树,则图上的非树边只有返祖边,没有横叉边。\(1\)类点考虑在这棵dfs树的基础上求出所有\(1\)类点:考虑\(fa_u\tou\)这条边被几条返祖边覆盖了,由于这是一个强连通分量,所以子树中至少有一条返祖边覆......
  • 题解:CF1992F Valuable Cards
    Part1:前言题目翻译在他最喜欢的咖啡馆里,Kmes再次想尝尝皮草大衣下的鲱鱼。以前,这对他来说并不难,但咖啡馆最近推出了一项新的购买政策。现在,为了进行购买,Kmes需要解决以下问题:在他面前摆放着\(n\)张不同价格的卡,第\(i\)张卡的价格为\(a_i\),在这些价格中没有整数\(x\)。K......
  • 题解:P9437 一棵树
    题目传送门明显的换根dp,感觉是道不错的换根dp练习题。题意一棵\(n\)个节点的树,点带权,定义\(w(x,y)=\overline{a_x\dotsa_y}\)。求\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}w(i,j)\bmod998244353\)。思路我们不妨先求出\(i=1\)时的\(\sumw(i,j)\),再求\(......
  • [SDOI2012] 走迷宫 题解
    [SDOI2012]走迷宫题目描述Morenan被困在了一个迷宫里。迷宫可以视为\(n\)个点\(m\)条边的有向图,其中Morenan处于起点\(s\),迷宫的终点设为\(t\)。可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿着一条从该点出发的有向边,到达另一个点。这样,Morenan走的步数可能......
  • 2024年暑期2024牛客暑期多校训练营1 C和H题解
    C题SumofSuffixSums题目大意:开始是给你一空数组,要经历q次操作,每次操作都会给出两个数字t和v,其中要从数组末尾去走元素t次,最后加上元素v。定义si=ai+ai+1+ai+2+ai+3+......+an,最后求s1+s2+s3+.......+sn的总和。最后答案注意取模。 题解:注意到sum的总和其实就......
  • CF512D Fox And Travelling 题解
    Description给定一张\(n\)个点\(m\)条边的无向图。一个点只有当与它直接相连的点中最多只有一个点未被选择过时才可被选择。询问对于每个\(k\in[0,n]\),有序选择\(k\)个点的方案数。\(n\le100\),\(m\le\frac{n(n-1)}2\),答案对\(10^9+9\)取模。Solution容易发......
  • [COCI2015-2016#1] UZASTOPNI 题解
    前言题目链接:洛谷。题意简述一棵有根树,节点数\(n\leq10^5\),每个点有权值\(v_i\leq2000\),现在选出一些点,满足:一个点的父亲点若未被选择则其不能被选择。所选点的集合内不能有相同的权值。对于每一个选择的点,其子树中所有被选择点的权值必须可以构成公差为\(1\)的等......
  • 2024牛客暑期多校训练营2(部分题目题解)
    2024牛客暑期多校训练营2(部分题目题解)C.RedWalkingonGrid题意:给定只有红白的2*n个格子,只能走红色各自且只能上下左右走,问最多可以走多少红色格子。题解:左右走:dp[0][i]=dp[0][i-1]+1;上下走:intk1=dp[0][i];intk2=dp[1][i];dp[0][i]=max(dp[0][i],k2+......
  • 20240722题解
    孩子们,我回来了......