zoukankan      html  css  js  c++  java
  • [HEOI2016&TJOI2016] 排序(线段树)

    4552: [Tjoi2016&Heoi2016]排序

    Time Limit: 60 Sec  Memory Limit: 256 MB
    Submit: 2703  Solved: 1386
    [Submit][Status][Discuss]

    Description

    在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题
    ,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排
    序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q
    位置上的数字。

    Input

    输入数据的第一行为两个整数n和m。n表示序列的长度,m表示局部排序的次数。1 <= n, m <= 10^5第二行为n个整
    数,表示1到n的一个全排列。接下来输入m行,每一行有三个整数op, l, r, op为0代表升序排序,op为1代表降序
    排序, l, r 表示排序的区间。最后输入一个整数q,q表示排序完之后询问的位置, 1 <= q <= n。1 <= n <= 10^5
    ,1 <= m <= 10^5

    Output

     输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。

    Sample Input

    6 3
    1 6 2 5 3 4
    0 1 4
    1 3 6
    0 2 4
    3

    Sample Output

    5

    这题直接排序肯定T到飞起,然后我们考虑其他做法(废话)
    瞎yy仔细分析后这也是个区间问题阿,考虑能不能用线段树维护。
    发现说是排序,但是最主要的关系还是之和大小关系有关啊,所以把这个问题抽象成一个01序列
    我们可以二分答案,每次check都把所有操作重新进行一遍。这只是个大体思路,我们还要考虑其正确性。
    为什么要二分答案,因为把问题转化成01序列后0或1代表该数与目标的大小关系,如果当前的该位置比目标大,那肯定是将区间左断点变大啊
    至于决策单调性,博主比较mengbi。有大佬会可以指出阿
    现在我们考虑怎么对每个更改进行操作,前面我们说过,01代表的是某个数与目标的大小关系,那我们在排序时只需利用这个性质,对于升序排序,把区间中所有0甩到左边,把1甩到右边,如果降序反过来。
    这样我们在二分答案时只需检测询问位置是否为1即可。
    对于这这些操作只需维护一棵支持区间覆盖,区间修改的线段数即可。
    注意点:在懒标记下传和赋值时,要直接赋值而不是累加。
        要加特判(代码中有注释),因为check()函数中的 change(1,1,n,ql[i],ql[i]+num-1,1)会导致右端点小于左端点
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<vector>
      7 #include<queue>
      8 const int N=1e5+10;
      9 using namespace std;
     10 int mid,sum1,q;
     11 int n,m;
     12 int a[N];
     13 struct node{
     14     int l,r,opt;
     15 }ask[N];
     16 struct NODE{
     17     int l,r,val,f;
     18 }tr[N<<2];
     19 void build(int p,int l,int r){//cout<<"B"<<endl;
     20     tr[p].l=l,tr[p].r=r;
     21     if(l==r){//cout<<"break"<<endl;
     22         tr[p].f=-1;
     23         tr[p].val=(a[l]>=mid);
     24         return ;
     25     }
     26     tr[p].f=-1;
     27     int mid=(l+r)>>1;
     28     build(p<<1,l,mid);
     29     build(p<<1|1,mid+1,r);
     30     tr[p].val=tr[p<<1].val+tr[p<<1|1].val;
     31 }
     32 void down(int p){
     33     if(tr[p].f<0) return ;
     34     tr[p<<1].f=tr[p].f;
     35     tr[p<<1|1].f=tr[p].f;//lanbiaojizhijiefugai
     36     tr[p<<1].val=(tr[p<<1].r-tr[p<<1].l+1)*tr[p].f;
     37     tr[p<<1|1].val=(tr[p<<1|1].r-tr[p<<1|1].l+1)*tr[p].f;
     38     tr[p].f=-1;
     39 }
     40 void change(int p,int l,int r,int val){
     41     if(l<=tr[p].l&&tr[p].r<=r){
     42         tr[p].f=val;
     43         tr[p].val=(tr[p].r-tr[p].l+1)*val;//zhijiefuzhi//
     44         return ;
     45     }
     46     if(l>tr[p].r||r<tr[p].l) return ;
     47     down(p);
     48     int mid=(tr[p].l+tr[p].r)>>1;
     49     if(l<=mid) change(p<<1,l,r,val);
     50     if(r>mid) change(p<<1|1,l,r,val);
     51     tr[p].val=tr[p<<1].val+tr[p<<1|1].val;
     52 }
     53 void query(int p,int l,int r){//cout<<p<<" "<<l<<" "<<r<<endl;
     54     if(l<=tr[p].l&&tr[p].r<=r){//cout<<"break"<<endl;
     55         sum1+=tr[p].val;//
     56         return ;
     57     }
     58     if(l>tr[p].r||r<tr[p].l) return ;//特判
     59     down(p);
     60     int mid=(tr[p].l+tr[p].r)>>1;
     61     if(l<=mid)query(p<<1,l,r);
     62     if(r>mid)query(p<<1|1,l,r);
     63 }
     64 bool check(int x){
     65     build(1,1,n);
     66     for(int i=1;i<=m;i++){
     67         sum1=0;query(1,ask[i].l,ask[i].r);
     68         if(ask[i].opt==0){//升序
     69             //cout<<"Q"<<endl;
     70             change(1,ask[i].l,ask[i].r-sum1,0);//
     71             change(1,ask[i].r-sum1+1,ask[i].r,1);//
     72         }
     73         else{
     74             //cout<<"Q"<<endl;
     75             change(1,ask[i].l+sum1,ask[i].r,0);
     76             change(1,ask[i].l,ask[i].l+sum1-1,1);
     77         }
     78     }
     79     //for(int i=1;i<=n;i++) cout<<tr[i].val<<" ";
     80     sum1=0;
     81     query(1,q,q);
     82     //cout<<sum1<<endl;
     83     if(sum1) return true;
     84     else return false;
     85 }
     86 int main(){
     87     //freopen("sort9.in","r",stdin);
     88     scanf("%d%d",&n,&m);
     89     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
     90     for(int i=1;i<=m;i++){
     91         scanf("%d%d%d",&ask[i].opt,&ask[i].l,&ask[i].r);
     92     }
     93     scanf("%d",&q);
     94     int l=1,r=n,ans;
     95     while(l<r){//cout<<"K"<<endl;
     96         mid=(l+r)>>1;//cout<<l<<" "<<r<<" "<<mid<<endl;
     97         //cout<<check(mid)<<endl;
     98         if(check(mid)) ans=mid/*?*/,l=mid+1;
     99         else r=mid;
    100     }
    101     printf("%d",ans);
    102 }
    View Code
  • 相关阅读:
    IIS无法显示 XML 页
    asp.net实现sql存取图片
    微软的面试题
    IIS配置.Net问题大全
    Asp.Net调用WebService
    生活本无常,前路更精彩
    【转载】碰到讨厌的老板怎么办
    xxxx不必xx尽,留些xxxx
    【BLOG】Mr梵谷
    机会,从来都是留给有准备的你
  • 原文地址:https://www.cnblogs.com/leom10/p/11272836.html
Copyright © 2011-2022 走看看