首页 > 其他分享 >【五一省选集训day4】Mansion

【五一省选集训day4】Mansion

时间:2024-09-10 18:51:38浏览次数:1  
标签:ch 省选 day4 sqrt write int que Mansion define

【五一省选集训day4】Mansion

注意,本题要求输出最大值,不要把最大值看成编号……srds 好像只有我看错了。

这个东西一看就很能用莫队做。

用莫队按 \(l\) 分块,再按 \(r\) 排序。维护一棵线段树,每次移动对线段树进行单点修改和区间求 \(\max\),一共 \(n\sqrt{n}\) 次移动,总时间复杂度是 \(O(n\sqrt{n}\log n)\) 的。可以获得 \(80pts\)。

感觉根号是不好消的,但是这个 \(\log\) 就看起来很能优化。

因为是求 \(\max\) 我们考虑回滚莫队来避免减法。回滚莫队也是 \(O(n\sqrt{n})\) 的。注意到我们每次移动都要修改,修改 \(O(n\sqrt{n})\) 次,而查询最大值只有 \(O(n)\) 次。这个 \(\sqrt{n}\) 的差距让我们想到用分块来代替线段树做。线段树两种操作都是 \(\log\) 的,但分块是修改 \(O(1)\),查询 \(O(\sqrt{n})\) 的!改成分块,总时间复杂度 \(O\sqrt{n}\)。

注意回滚莫队第一块除以 \(T\) 是 \(0\),而为空的 \(que_0\) 除以 \(T\) 也是 \(0\),记得初始化 \(\frac{que_0}{T}=-1\),否则 \(0\) 会成为第一块开头,而不是 \(1\)。害我调了一下午

code

#include<bits/stdc++.h>
//#define LOCAL
#define int ll
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
#define isdigit(x) ((x>='0')&&(x<='9'))
#define ls u<<1
#define rs u<<1|1
using namespace std;
typedef long long ll;
const int N=150500,T=395;
template <typename T>
inline void read(T &x){
	x=0;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
}
template <typename T>
inline void write(T x){
	static int st[20];
	int cnt=0;
	do{
		st[cnt++]=x%10;
		x/=10;
	}while(x);
	while(cnt) putchar(st[--cnt]+'0');
}
template <typename T>
inline void write (T x,char ch){
	write(x);
	putchar(ch);
}
int n,m,q,t;
struct node{
	int a,b;
}h[N];
struct que{
	int t,id,l,r,vl,vr;
}qu[N];
int l,r,vl,vr;
bool cmp(que a,que b){
	return a.t!=b.t?a.t<b.t:a.r<b.r;
}
ll s[N],mx[N/T+10],mxt[N/T+10];
ll anss[N];
void add(int k){
	int a=h[k].a,b=h[k].b;
	s[a]+=b;
	int ta=a/T;
	mx[ta]=max(mx[ta],s[a]);
}
void add2(int k){
	int a=h[k].a,b=h[k].b;
	s[a]+=b;
	int ta=a/T;
	mxt[ta]=max(mxt[ta],s[a]);
}
void del2(int k){
	int a=h[k].a,b=h[k].b;
	s[a]-=b;
}
ll s2[N];
int L,R;
ll solve(ll l,ll r){
	ll ans=0;
	if(l/T==r/T){
		rep(i,l,r) ans=max(ans,s[i]);
	}else{
		rep(i,l,l/T*T+T-1) ans=max(ans,s[i]);
		rep(i,l/T+1,r/T-1) ans=max(ans,mxt[i]);
		rep(i,r/T*T,r) ans=max(ans,s[i]);
	}
	return ans;
}
signed main(){
	#ifdef LOCAL
	freopen("in.txt","r",stdin);
	freopen("my2.out","w",stdout);
	#endif
	read(n),read(m),read(q);
	rep(i,1,n){
		read(h[i].a);
	}
	rep(i,1,n) {
		read(h[i].b);
	}
	rep(i,1,q){
		read(l),read(r),read(vl),read(vr);
		qu[i]={l/T,i,l,r,vl,vr};
	}
	sort(qu+1,qu+q+1,cmp);
	qu[0].t=-1;
	rep(i,1,q){
		t=qu[i].t,l=qu[i].l,r=qu[i].r,vl=qu[i].vl,vr=qu[i].vr;
		ll ans=0;
		if(l/T==r/T){
			qu[i].t=qu[i-1].t;
			rep(j,l,r){
				int a=h[j].a,b=h[j].b;
				if(a<vl||a>vr) continue;
				s2[a]+=b;
				ans=max(ans,s2[a]);
			}
			rep(j,l,r){
				int a=h[j].a;
				s2[a]=0;
			}
		}else{
			L=t*T+T;
			if(t!=qu[i-1].t){
				memset(s,0,sizeof(s));
				memset(mx,0,sizeof(mx));
				R=L-1;
			}
			while(R<r) {
				R++;
				add(R);
			}
			memcpy(mxt,mx,sizeof(mx));
			while(L>l){
				L--;
				add2(L);
			}
			ans=solve(vl,vr);
			L=t*T+T;
			while(L>l){
				L--;
				del2(L);
			}
		}
		anss[qu[i].id]=ans;
	}
	rep(i,1,q) write(anss[i],'\n');
}

标签:ch,省选,day4,sqrt,write,int,que,Mansion,define
From: https://www.cnblogs.com/liyixin0514/p/18406965

相关文章

  • 24暑假算法刷题 | Day41 | 动态规划 IX | LeetCode 188. 买卖股票的最佳时机 IV,309.
    目录188.买卖股票的最佳时机IV题目描述题解309.买卖股票的最佳时机含冷冻期题目描述题解714.买卖股票的最佳时机含手续费题目描述题解188.买卖股票的最佳时机IV点此跳转题目链接题目描述给你一个整数数组prices和一个整数k,其中prices[i]是某支给定......
  • 实训day43(9.4)
    一、前期准备1、配置主机映射[root@k8s-master~]#vim/etc/hosts192.168.8.168 k8s-master192.168.8.176 k8s-node1192.168.8.177 k8s-node2[root@k8s-master~]#pingk8s-master2、配置yum源[[email protected]]#vimkubernetes.repo[kuberne......
  • 实训day42(9.3)
    ⼀、编排分类单机容器编排:docker-compose容器集群编排:dockerswarm、mesos+marathon、kubernetes应⽤编排:ansible(模块,剧本,⻆⾊)⼆、系统管理进化史1.传统部署时代早期,各个组织是在物理服务器上运⾏应⽤程序。由于⽆法限制在物理服务器中运⾏的应⽤程序资源使⽤,......
  • 代码随想录day49 || 42、接雨水 84、柱状图中最大的矩形
    42、接雨水functrap(height[]int)int{ //双指针思路,按照列计算雨水高度,分别计算每一列左右高于当前高度的最高柱子高度,然后通过min(left,right)-height[i]得出当前列的雨水体积 varresint varleft,rightint fori:=1;i<len(height)-1;i++{ left,right=......
  • 代码随想录day48 || 739, 每日温度 496, 下一个更大元素 I 503, 下一个更大元素II
    739每日温度funcdailyTemperatures(temperatures[]int)[]int{ //双指针 varres=make([]int,len(temperatures)) fori:=0;i<len(temperatures);i++{ forj:=i+1;j<len(temperatures);j++{ iftemperatures[j]>temperatures[i]{ res[i]=j......
  • 代码随想录算法day4 - 哈希表2
    题目1454.四数相加II给你四个整数数组nums1、nums2、nums3和nums4,数组长度都是n,请你计算有多少个元组(i,j,k,l)能满足:0<=i,j,k,l<nnums1[i]+nums2[j]+nums3[k]+nums4[l]==0示例1:输入:nums1=[1,2],nums2=[-2,-1],nums3=[-1,2],nums4......
  • leetcode刷题day4|链表部分(24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点、
    前言:链表练习的第二天,对链表的理解加深了24.两两交换链表中的节点这个题一开始的思路是用cur和next两个指针来做,但是绕来绕去绕迷糊了,最后超时了。把错误的代码放在下面警醒大家:主要问题出现在这两行代码,next.next发生了更改。next.next=next.next.next;next.next.nex......
  • 代码随想录day46 || 647 回文子串, 516 最长回文子序列
    647回文字串funccountSubstrings(sstring)int{ //动规五部曲 //dp[i][j]表示s[i:j+1]区间是否是一个回文 //ifs[i]==s[j]{ifi-j<=1||dp[i+1][j-1]==true{dp[i][j]==true}} //初始化为false //从下往上,从左往右 //print varcountint var......
  • 代码随想录算法day4 - 链表2
    题目124.两两交换链表中的节点给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。示例1:输入:head=[1,2,3,4]输出:[2,1,4,3]示例2:输入:head=[]输出:[]示例3:输入:head=[1]输出:[1]......
  • 代码随想录day45 || 115 不同子序列, 583 两个字符串删除操作, 72 编辑距离
    115不同子序列funcnumDistinct(sstring,tstring)int{ //动态规划,思考一下判断连续和不连续的区别,如果相等都是左上角+1,如果不等,连续情况就是直接等于左上角,不连续情况直接归零 //dp[i][j]表示s[i]中存在t[j]结尾的的个数 //递推公式,不要求连续字串,所以,如果s[i......