首页 > 其他分享 >P4747 [CERC2017] Intrinsic Interval

P4747 [CERC2017] Intrinsic Interval

时间:2024-07-03 14:08:46浏览次数:18  
标签:std pr return int Interval MAXN Intrinsic P4747 define

先说线段数做法

发现一个区间连续有一个性质:这个区间\([l,r]\)存在相邻两个数的对数是\(r-l\)

考虑离线下来,线段数维护每个区间存在相邻数的对数,当前是\(i\),每次扫描新的一个\(a[i]\)进来,因为我扫描线是钦定了以\(i\)位右端点,所以若\(a[i]-1\)的位置在\(a[i]\)前面,我就将\([1,a[i]-1]\)区间+1,因为这样\(l\)取\([1,a[i]-1]\)这个范围,我的相邻对数都会+1。\(a[i]+1\)同理。

然后处理查询的话,存在合法的\([l,r]\),就是\(query(l)=r-l\),那我每次线段数赋初值都是下标,就只要判断是否等于\(r\)就可以了,就是看query(1~L)的最大值有没有等于R的。有一个必须的优化:如果\([1,l]\)最大值都到大不了\(r\),那么\([1,l']\)且\(l'<l\)都不可以了

#include<bits/stdc++.h>
#define vd void 
#define MAXN 100005
#define pr std::pair<int,int>
#define fi first
#define se second 
int gi(){
	char c;int x=0,f=0;
	while(!isdigit(c=getchar()))f|=(c=='-');
	while(isdigit(c))x=(x*10)+(c^48),c=getchar();
	return f?-x:x;
}
int n,m,a[MAXN],pos[MAXN];
std::vector<pr>q[MAXN];
std::priority_queue<pr>pq;
pr ans[MAXN];
namespace segtree{ //维护最大值和最大值的位置
#define ls x<<1
#define rs x<<1|1
#define mid ((l+r)>>1)
	int maxi[MAXN<<2],pmax[MAXN<<2],tag[MAXN<<2];
	vd up(int x){
		if(maxi[ls]>maxi[rs])maxi[x]=maxi[ls],/*std::cout<<"$"<<pmax[x]<<' '<<pmax[ls]<<'\n',*/pmax[x]=pmax[ls];
		else maxi[x]=maxi[rs],pmax[x]=pmax[rs];
	}
	vd addtag(int x,int w){maxi[x]+=w,tag[x]+=w;}
	vd down(int x){
		if(!tag[x])return;
		addtag(ls,tag[x]),addtag(rs,tag[x]);
		tag[x]=0;
	}
	vd build(int x,int l,int r){
		if(l==r)return maxi[x]=pmax[x]=l,void();
		build(ls,l,mid),build(rs,mid+1,r);up(x);
	}
	vd upd(int x,int l,int r,int qx,int qy,int w){
		if(r<qx||l>qy)return;
		if(l>=qx&&r<=qy){addtag(x,w);return;}
		down(x);
		upd(ls,l,mid,qx,qy,w),upd(rs,mid+1,r,qx,qy,w);
		up(x);
	}
	pr query(int x,int l,int r,int qx,int qy){
		if(r<qx||l>qy)return {0,0};
		if(l>=qx&&r<=qy)return std::make_pair(maxi[x],pmax[x]);
		down(x);
		pr wl=query(ls,l,mid,qx,qy),wr=query(rs,mid+1,r,qx,qy);
		if(wl.fi>wr.fi)return wl;
		else return wr;
	}
}
using namespace segtree;
bool calc(pr l,int r){
	pr tmp=query(1,1,n,1,l.fi);
	if(tmp.fi==r){ans[l.se]=std::make_pair(tmp.se,r);return 1;}
	return 0;
}
int main(){
	n=gi();for(int i=1;i<=n;i++)a[i]=gi(),pos[a[i]]=i;
	m=gi();
	for(int i=1;i<=m;i++){
		int x=gi(),y=gi();
		q[y].emplace_back(std::make_pair(x,i));
	}
	build(1,1,n);
	for(int i=1;i<=n;i++){
		if(a[i]-1>=1&&pos[a[i]-1]<=i)upd(1,1,n,1,pos[a[i]-1],1);
		if(a[i]+1<=n&&pos[a[i]+1]<=i)upd(1,1,n,1,pos[a[i]+1],1);
		for(pr j:q[i])pq.push(j);
		while(!pq.empty()){
			pr u=pq.top();
			if(calc(u,i))pq.pop();
			else break;
		}
	}
	for(int i=1;i<=m;i++)printf("%d %d\n",ans[i].fi,ans[i].se);
	return 0;
}

精髓还是把一个要求的东西挖掘一些能维护的性质或信息出来

标签:std,pr,return,int,Interval,MAXN,Intrinsic,P4747,define
From: https://www.cnblogs.com/xiaboxin/p/18281513

相关文章

  • D - Intersecting Intervals(abc355)
    题意:有n个区间,找出俩俩区间相交的个数分析:设初始俩俩相交,找出不相交的(不同区间l>r),减去即可#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;intmain(){   ios::sync_with_stdio(false);   intn,l[n+10],r[n+10];   cin>>n;  ......
  • [题解]AT_dp_w Intervals
    思路首先考虑较为普通的DP。定义\(dp_{i,j}\)表示在前\(i\)个位置中,最后一个1在\(j\)的最大分数,显然有:\[dp_{i,j}=\left\{\begin{matrix}\max_{k=1}^{i-1}\{dp_{i-1,k}\}+\sum_{l_k\leqj\wedger_k=i}{a_k}&(i=j)\\dp_{i-1,j}+\sum......
  • 核心(Hutool-core)日期时间(计时器工具-TimeInterval)
    Hutool通过封装TimeInterval实现计时器功能,即可以计算方法或过程执行的时间。TimeInterval支持分组计时,方便对比时间。使用TimeIntervaltimer=DateUtil.timer();//---------------------------------//-------这是执行过程//---------------------------------timer.int......
  • 五月踩坑指南之clearInterval()定时器不起效果
    clearInterval定时器不起效果问题代码解决方案:将定时器增加到数组内,循环清除另外的方案问题代码lettimer=nulltimer=setInterval(()=>{执行的方法},1000)timer=setInterval(()=>{执行的方法},1000)if(timer){clearInterval(this.timer)timer=null;}此......
  • ABC 355 D题Intersecting Intervals
    题意现在有n条线段,每条线段的左端点和右端点依次给出,求有多少对线段有交集。思路考虑正难则反的想法,我们考虑着n条线段全部两两相交的时候,那么答案就是(n-1)*n/2,现在我们要求出有多少对线段是不相交的。当两条线段不相交的时候,显然有其中一条线段的左端点严格大于另一条线......
  • CF1089I Interval-Free Permutations
    标签:析合树析合树就是用来处理这一种值域连续段的问题的。OI-wiki上对于析合树的讲解。我们回顾一下题目,要求不存在长度为\([2,n-1]\)之间的连续段,换句话说,就是根节点下恰有\(n-1\)个节点,且没有任何一个字段是题目中要求的连续段。我们记这样的答案为\(A_n\)也就......
  • D - Intersecting Intervals
    D-IntersectingIntervals 思路对于区间重合问题,经典做法对left进行排序,然后进行统计计数。写了一版TLE,反思有冗余计数问题。计算每一个区间的覆盖数目,不需要TLE版本逐个往后数,只需要使用lower_bound找出第一个大于等于ri+1 的位置,即可得到与i区间重合区间......
  • setTimeout模拟interval
    functionrunTimer(list=[ { delay:2000, text:'第一步延迟2s' }, { delay:3000, text:'第二步延迟3s' }, { delay:1000, text:'第三步延迟1s' }, ],cb=(text)=>{ console.log('渲染回调&......
  • alertmanager 设置 repeat_interval 不生效
    这个问题其实并不是repeat_interval真的没生效,而是告警没有重复,人家发的是新的告警,没有命中repeat_interval规则。举个栗子-alert:HighCpuLoadexpr:100-(avg(irate(node_cpu_seconds_total{mode="idle"}[5m]))by(instance)*100)>70for:1m......
  • [atcode abc349] D - Divide Interval
    解决方法,贪心。importjava.io.*;importjava.math.BigInteger;importjava.util.*;publicclassMain{publicstaticvoidmain(String[]args)throwsIOException{longL,R;L=rd.nextLong();R=rd.nextLong();PrintWri......