• [CERC2017]Intrinsic Interval


    题意

    给出一个n排列,m次询问,每次查询长度最小的区间,使得这个区间排序后出现连续的整数(即相邻的差为1),并且包含(或等于)区间[l,r]。若长度相等,取l端点最小的。

    n,m<=1E5


    思考

    重要的性质:

    1.一个区间是连续的,当且仅当其存在r-l个无序二元组(x,y),满足|x-y|=1。

    2.若两个连续区间有交,其交必然是连续的。因为交的部分要同时满足左右部分是连续的。若交不连续,至多满足一个部分连续。

    根据性质2,可以知道对于某个询问,可以通过不断移动要求的右端点,直到出现的所有的连续区间至少有一个完全覆盖了它。此时长度最小的一定是最优的。

    根据性质1,可以先离线,再依次将数组中的每个数产生的贡献加入线段树。具体地讲,对于数ai,若ai-1,ai+1出现的位置在i左侧,则在区间[1,位置ai-1],[1,位置ai+1]加1,表示多出了一个差为1的无序二元组。那只要知道哪些[l,i]满足vall+l=r即可(r-l=vall)。方便起见,最开始建树时vali=i,则只要查询vall=i。

    由于一个区间满足条件的无序二元组最多为r-l个,维护最大值及其位置即可。

    接下来是询问部分。离线之后,按r排序,每次加入r=i的询问至set(实际是multiset,因为有重)中。set中按l从大到小排序。这样一来,每次查询尽可能大的左端点,一旦无法覆盖就能break。

    复杂度O(nlogn+mlogm)


    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1E5+5;
      4 int n,m,a[maxn],ansX[maxn],where[maxn],ansY[maxn];
      5 int t[maxn*4],tag[maxn*4],maxVal[maxn*4],maxPos[maxn*4];
      6 struct query
      7 {
      8     int x,y,id;
      9     bool operator < (query A)const
     10     {
     11         if(x!=A.x)
     12             return x>A.x;
     13         return y<A.y;
     14     }
     15 }q[maxn];
     16 vector<query>wait[maxn];
     17 void pushdown(int l,int r,int num)
     18 {
     19     if(!tag[num])
     20         return;
     21     maxVal[num]+=tag[num];
     22     if(l==r)
     23     {
     24         tag[num]=0;
     25         return;
     26     }
     27     tag[num<<1]+=tag[num];
     28     tag[num<<1|1]+=tag[num];
     29     tag[num]=0;
     30 }
     31 void update(int l,int r,int num)
     32 {
     33     pushdown(l,r,num);
     34     if(l==r)
     35         return;
     36     int mid=(l+r)>>1;
     37     pushdown(l,mid,num<<1);
     38     pushdown(mid+1,r,num<<1|1);
     39     if(maxVal[num<<1]<=maxVal[num<<1|1])
     40     {
     41         maxVal[num]=maxVal[num<<1|1];
     42         maxPos[num]=maxPos[num<<1|1];
     43     }
     44     else
     45     {
     46         maxVal[num]=maxVal[num<<1];
     47         maxPos[num]=maxPos[num<<1];
     48     }
     49 }
     50 void build(int l,int r,int num)
     51 {
     52     if(l==r)
     53     {
     54         maxVal[num]=l;
     55         maxPos[num]=l;
     56         return;
     57     }
     58     int mid=(l+r)>>1;
     59     build(l,mid,num<<1);
     60     build(mid+1,r,num<<1|1);
     61     update(l,r,num);
     62 }
     63 void add(int L,int R,int l,int r,int x,int num)
     64 {
     65     update(l,r,num);
     66     if(L<=l&&r<=R)
     67     {
     68         tag[num]+=x;
     69         update(l,r,num);
     70         return;
     71     }
     72     if(r<L||R<l)
     73         return;
     74     int mid=(l+r)>>1;
     75     add(L,R,l,mid,x,num<<1);
     76     add(L,R,mid+1,r,x,num<<1|1);
     77     update(l,r,num);
     78 }
     79 int ask(int L,int R,int l,int r,int x,int num)
     80 {
     81     update(l,r,num);
     82     if(L<=l&&r<=R)
     83     {
     84         if(maxVal[num]!=x)
     85             return -1;
     86         return maxPos[num];
     87     }
     88     if(r<L||R<l)
     89         return -1;
     90     int mid=(l+r)>>1;
     91     return max(ask(L,R,l,mid,x,num<<1),ask(L,R,mid+1,r,x,num<<1|1));
     92 }
     93 void out(int l,int r,int num)
     94 {
     95     update(l,r,num);
     96     if(l==r)
     97     {
     98         cout<<maxVal[num]<<' ';
     99         return;
    100     }
    101     int mid=(l+r)>>1;
    102     out(l,mid,num<<1);
    103     out(mid+1,r,num<<1|1);
    104 }
    105 int main()
    106 {
    107     ios::sync_with_stdio(false);
    108     cin>>n;
    109     build(1,n,1);
    110     for(int i=1;i<=n;++i)
    111     {
    112         cin>>a[i];
    113         where[a[i]]=i;
    114     }
    115     cin>>m;
    116     for(int i=1;i<=m;++i)
    117     {
    118         cin>>q[i].x>>q[i].y;
    119         q[i].id=i;
    120         wait[q[i].y].push_back(q[i]);
    121     }
    122     where[n+1]=where[0]=n+1;
    123     multiset<query>S;
    124     for(int i=1;i<=n;++i)
    125     {
    126         if(where[a[i]-1]<i)
    127             add(1,where[a[i]-1],1,n,1,1);
    128         if(where[a[i]+1]<i)
    129             add(1,where[a[i]+1],1,n,1,1);
    130         for(int j=0;j<wait[i].size();++j)
    131         {
    132 //            cout<<"NEW"<<wait[i][j].x<<' '<<wait[i][j].y<<endl;
    133             S.insert(wait[i][j]);
    134         }
    135         while(!S.empty())
    136         {
    137             set<query>::iterator pt=S.begin();
    138 //            cout<<(*pt).x<<' '<<(*pt).y<<" "<<S.size()<<"---"<<endl;
    139             int pos=ask(1,(*pt).x,1,n,i,1);
    140             if(pos==-1)
    141                 break;
    142             ansX[(*pt).id]=pos;
    143             ansY[(*pt).id]=i;
    144             S.erase(pt);
    145         }
    146     }
    147     for(int i=1;i<=m;++i)
    148         cout<<ansX[i]<<" "<<ansY[i]<<endl;
    149     return 0;
    150 }
    View Code
  • 相关阅读:
    计算机基础
    如何增加一个IT产品的用户黏性
    计算机相关专业一门课程一个案例
    【2012年6月14日】中兴发布Grand(智观)N970
    bmp格式浅析
    3Dbook的使用
    中英文翻译格式
    软件学习书籍推荐
    WEB开发基础
    PHP学习
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/10813207.html
Copyright © 2020-2023  润新知