zoukankan      html  css  js  c++  java
  • P4747 [CERC2017]Intrinsic Interval

    题目链接

    题意分析

    首先对于一个区间[L,R] 可以发现:Max-Min+L-R=0

    如果你不知道该怎么维护的话 请看看这道题【CF526F Pudding Monsters】

    现在关键是 对于一个区间怎么维护

    首先可以证明的是 一个字串的本征区间是唯一的

    因为两个区间的交也是区间 所以两个区间都包含这个区间的话 那么二者的交符合条件而且是更优的

    所以我们直接针对长度求最优就可以了

    首先 我们把所有的询问子串按照右端点排序 然后进行扫描 扫到的加入一个堆里 按照左端点从大到小进行排序 堆顶的是左端点最大的子串

    然后 我们使用线段树维护当前函数 (f(x)=Max-Min+l-r) 维护答案的最小值 以及整个最小值最靠右的位置 因为当前右端点确定 所以我们肯定希望左端点尽可能的向右

    对于当前堆顶的元素也就是子串 如果说子串的左端点往左存在符合要求的点的话 那么就是我们要求的点

    疑点:

    1.如果对于一个子串来说 后面存在更优的怎么办?

    假设说对于当前的子串求得的本征区间为[L1,R1] 但是实际上对应有更优的L2,R2

    那么由于因为两个区间的交也是区间 所以实际上会有更优的[L2,R1]

    2.如果堆顶的子串一直找不到答案 那么会不会耽误堆里其他的子串找到答案?

    不会有这种情况发生的

    你们认为会耽误的只有这种情况

    无标题.png

    但是为什么会耽误呢?

    我们是按照右端点顺序加入堆的 在堆顶元素入堆之前还没有找到答案出堆的话 堆顶的本征区间一定被堆下面子串的本征区间包含的

    所以我们就可以好好求了

    CODE:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define N 100080
    #define inf 2147483600
    using namespace std;
    int n,m,tpx,tpy;
    int num[N],stx[N],sty[N];
    int ansl[N],ansr[N];
    struct Node
    {
    	int le,ri,id;
    	friend bool operator < (const Node &A,const Node &B)
    	{return A.le==B.le ? A.ri<B.ri : A.le<B.le;}
    }qe[N];
    priority_queue<Node> que;
    struct Tree
    {
    	int Min,nowat,tag;
    }tre[N<<2];
    bool cmp(const Node &A,const Node &B)
    {return A.ri==B.ri ? A.le<B.le : A.ri<B.ri;}
    void pushup(int now)
    {
    	if(tre[now<<1].Min<tre[now<<1|1].Min)
    	{
    		tre[now].Min=tre[now<<1].Min;
    		tre[now].nowat=tre[now<<1].nowat;
    	}
    	else
    	{
    		tre[now].Min=tre[now<<1|1].Min;
    		tre[now].nowat=tre[now<<1|1].nowat; 
    	}
    }
    void down(int now)
    {
    	tre[now<<1].Min+=tre[now].tag;
    	tre[now<<1|1].Min+=tre[now].tag;
    	tre[now<<1].tag+=tre[now].tag;
    	tre[now<<1|1].tag+=tre[now].tag;
    	tre[now].tag=0;
    }
    void build(int now,int le,int ri)
    {
    	tre[now].tag=0;
    	if(le==ri)
    	{
    		tre[now].Min=le;tre[now].nowat=le;
    		return;
    	}
    	int mid=(le+ri)>>1;
    	build(now<<1,le,mid);build(now<<1|1,mid+1,ri);
    	pushup(now);
    }
    void update(int now,int lenow,int rinow,int le,int ri,int d)
    {
    	if(le<=lenow&&rinow<=ri)
    	{
    		tre[now].Min+=d;
    		tre[now].tag+=d;
    		return;
    	}
    	if(tre[now].tag) down(now);
    	int mid=(lenow+rinow)>>1;
    	if(le<=mid) update(now<<1,lenow,mid,le,ri,d); 
    	if(mid<ri) update(now<<1|1,mid+1,rinow,le,ri,d);
    	pushup(now);
    }
    pair<int,int> query(int now,int lenow,int rinow,int le,int ri)
    {
    	if(le<=lenow&&rinow<=ri) return make_pair(tre[now].Min,tre[now].nowat);
    	if(tre[now].tag) down(now);
    	int mid=(lenow+rinow)>>1;pair<int,int> tmp1=make_pair(inf,0),tmp2=make_pair(inf,0);
    	if(le<=mid) tmp1=query(now<<1,lenow,mid,le,ri);
    	if(mid<ri) tmp2=query(now<<1|1,mid+1,rinow,le,ri);
    	if(tmp1.first==tmp2.first)
    	{
    		if(tmp1.second<tmp2.second) return tmp2;
    		else return tmp1;
    	}
    	else
    	{
    		if(tmp1.first<tmp2.first) return tmp1;
    		else return tmp2;
    	}
    }
    int main()
    {
    	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    	cin>>n;
    	for(int i=1;i<=n;++i) cin>>num[i];
    	cin>>m;
    	for(int i=1,x,y;i<=m;++i)
    	{
    		cin>>x>>y;qe[i]=(Node){x,y,i};
    	}
    //	sort(qe+1,qe+m+1);
    //	for(int i=1;i<=m;++i)
    //	printf("[%d] = (%d %d)
    ",i,qe[i].le,qe[i].ri);
    	sort(qe+1,qe+m+1,cmp);build(1,1,n);
    //	for(int i=1;i<=m;++i)
    //	printf("[%d] = (%d %d)
    ",i,qe[i].le,qe[i].ri);	
    //	for(int i=1;i<=n;++i) printf("%d%c",query(1,1,n,i,i).first,(i==n ? '
    ':' '));
    	for(int i=1,tail=1;i<=n;++i)
    	{
    //		printf("now at %d
    ",i);
    		update(1,1,n,1,n,-1);
    //for(int i=1;i<=n;++i) printf("%d%c",query(1,1,n,i,i).first,(i==n ? '
    ':' '));		
    		while(tail<=m&&qe[tail].ri<=i)
    		que.push(qe[tail++]);
    		while(tpx&&num[stx[tpx]]<num[i])
    		update(1,1,n,stx[tpx-1]+1,stx[tpx],num[i]-num[stx[tpx]]),--tpx;
    		stx[++tpx]=i;
    		while(tpy&&num[sty[tpy]]>num[i])
    		update(1,1,n,sty[tpy-1]+1,sty[tpy],num[sty[tpy]]-num[i]),--tpy;
    		sty[++tpy]=i;			
    //		printf("che2
    ");
    		while(!que.empty())
    		{
    			Node tmp=que.top();
    //			printf("now is %d
    ",tmp.id); 
    			int bian=tmp.le;
    //			printf("cdy
    ");
    			pair<int,int> nowtmp=query(1,1,n,1,bian);		
    			if(nowtmp.first==0) 
    			{
    				ansl[tmp.id]=nowtmp.second;
    				ansr[tmp.id]=i;
    				que.pop();
    			}
    			else break;
    		}
    //		printf("check3
    ");
    	}
    	for(int i=1;i<=m;++i) printf("%d %d
    ",ansl[i],ansr[i]);
    	return 0;	
    }
    
  • 相关阅读:
    Mac下mysql出现错误:ERROR 1055 (42000)
    单表查询
    外键的变种 三种关系
    Java8中Lambda表达式详解
    Java中的比较器Comparable、Comparator
    Java创建线程的方法
    java日期格式化
    Docker容器如何修改hosts
    使用postman可以正常访问,但是在应用中返回415状态码
    使用tcpdump进行抓包
  • 原文地址:https://www.cnblogs.com/LovToLZX/p/13861948.html
Copyright © 2011-2022 走看看