• Sorting (线段树+思维) ccpcwannafly


    Sorting

       

    0.00%

    提交人数:3

    通过人数:0

    题目描述

     

    你有一个数列a_1, a_2, dots, a_na1,a2,,an,你要模拟一个类似于快速排序的过程。有一个固定的数字xx。

    你要支持三种操作:

    • 询问区间[l, r][l,r]之间的元素的和,也就是sum_{i=l}^r a_ii=lrai
    • 对区间[l,r][l,r]进行操作,也就是说你把区间中所有的数字拿出来,然后把小于等于xx的数字按顺序放在左边,把大于xx的数字按顺序放在右边,把这些数字接起来,放回到数列中。比如说x=3x=3,你的区间里的数字是1,5,3,2,41,5,3,2,4,那么操作完之后区间里面的数字变为1,3,2,5,41,3,2,5,4。
    • 对区间[l,r][l,r]进行操作,也就是说你把区间中所有的数字拿出来,然后把大于xx的数字按顺序放在左边,把小于等于xx的数字按顺序放在右边,把这些数字接起来,放回到数列中。
     
     

    输入描述

     

    第一行三个整数n, q, x ( 1leq n, q leq 2*10^5, 0leq xleq 10^9)n,q,x(1n,q2105,0x109)表示元素的个数和询问的个数。

    接下来一行nn个整数a_1, a_2, dots, a_n(1leq a_ileq 10^9)a1,a2,,an(1ai109)。

    接下来qq行,每行三个正整数p, l, r (1leq pleq 3), 1leq lleq rleq np,l,r(1p3),1lrn表示操作种类和区间。

    输出描述

     

    对于每个第一种操作,输出一行,表示答案。

    样例输入 1 

    5 9 3
    1 5 3 2 4
    1 1 5
    2 1 5
    1 1 1
    1 2 2
    1 3 3
    1 4 4
    1 5 5
    3 3 5
    1 1 4
    

    样例输出 1

    15
    1
    3
    2
    5
    4
    13






    发现对题目总的操作,小于等于x的树的相对顺序不会改版,
    从前也讲过把操作序列转变成01序列的题,然后这个题也是。
    小于等于的变成0,大的变成1
    翻转就是 统计区间内又几个1,几个0,前面的一段赋值为0,后面的一段赋值为1,
    求和就是,单开两个数组按顺序存两种树,求前缀和,每次作差求答案。




      1 #include<bits/stdc++.h>
      2 #define CLR(a,b) memset(a,b,sizeof(a))
      3 using namespace std;
      4 typedef long long ll;
      5 const int maxn=200010;
      6 const int inf=0x3f3f3f3f;
      7 ll a[maxn];
      8 struct node{
      9     ll sum,lazy;
     10 }tr[maxn<<2];
     11 int n,q,pa,pb;
     12 ll x,prea[maxn],preb[maxn]; 
     13 void init(){
     14     pa=0,pb=0;
     15 }
     16 void build(int o,int l,int r){
     17     if(l==r){
     18         tr[o].sum=a[l];
     19         tr[o].lazy=-1;
     20         return ;
     21     }
     22     int mid=(l+r)>>1;
     23     build(o<<1,l,mid);
     24     build((o<<1)|1,mid+1,r);
     25     tr[o].sum=tr[o<<1].sum+tr[(o<<1)|1].sum;
     26     tr[o].lazy=-1;
     27 }
     28 void pushup(int o){
     29     tr[o].sum=tr[o<<1].sum+tr[o<<1|1].sum;
     30 }
     31 void pushdown(int o,int l,int r){
     32     if(tr[o].lazy!=-1){
     33         tr[o<<1].lazy=tr[o].lazy;
     34         tr[o<<1|1].lazy=tr[o].lazy;
     35         int mid=(l+r)>>1;
     36         tr[o<<1].sum=tr[o].lazy*(mid-l+1);
     37         tr[o<<1|1].sum=tr[o].lazy*(r-mid);
     38         tr[o].lazy=-1;
     39     }
     40 }
     41 void update(int o,int l,int r,int ql,int qr,ll val){
     42     if(ql<=l&&r<=qr){
     43         tr[o].lazy=val;
     44         tr[o].sum=val*(r-l+1);
     45         return;
     46     }
     47     pushdown(o,l,r);
     48     int mid=l+((r-l)>>1);
     49     if(ql<=mid)update(o<<1,l,mid,ql,qr,val);
     50     if(qr>=mid+1)update(o<<1|1,mid+1,r,ql,qr,val);
     51     pushup(o);
     52 }
     53 ll query(int o,int l,int r,int ql,int qr){
     54     if(ql<=l&&qr>=r)return tr[o].sum;
     55     pushdown(o,l,r);
     56     int mid=(l+r)>>1;
     57     ll ans=0;
     58     if(ql<=mid)ans=query(o<<1,l,mid,ql,qr);
     59     if(qr>=mid+1)ans+=query(o<<1|1,mid+1,r,ql,qr);
     60     return ans;
     61 }
     62 int op,u,v;
     63 int main(){
     64     while(cin>>n>>q>>x){
     65         init();
     66         for(int i=1;i<=n;i++)
     67         {
     68             scanf("%lld",&a[i]);
     69             if(a[i]<=x){
     70                 prea[++pa]=a[i];
     71                 prea[pa]+=prea[pa-1];
     72                 a[i]=0;
     73             }else{
     74                 preb[++pb]=a[i];
     75                 preb[pb]+=preb[pb-1];
     76                 a[i]=1;
     77             }
     78         }
     79         build(1,1,n);
     80         while(q--)
     81         {
     82             scanf("%d%d%d",&op,&u,&v);
     83             if(op==2){
     84                 ll tep=query(1,1,n,u,v);
     85                 tep=v-u+1-tep;
     86                 if(tep>0)
     87                 update(1,1,n,u,u+tep-1,0);
     88                 if(tep<v-u+1)
     89                 update(1,1,n,u+tep,v,1);
     90             }else if(op==1){
     91                 if(u==1){
     92                     ll tp=query(1,1,n,u,v);
     93                     ll ans=preb[tp];
     94                     ans+=prea[v-tp];
     95                     printf("%lld
    ",ans);
     96                     continue;
     97                 }
     98                 ll tp1=query(1,1,n,1,u-1);
     99                 ll tp2=query(1,1,n,1,v);
    100                 ll ans=preb[tp2]-preb[tp1];
    101                 tp1=u-1-tp1,tp2=v-tp2;
    102                 ans+=prea[tp2]-prea[tp1];
    103                 printf("%lld
    ",ans);
    104             }else{
    105                 ll tep=query(1,1,n,u,v);
    106                 if(tep>0)
    107                 update(1,1,n,u,u+tep-1,1);
    108                 if(tep<v-u+1)
    109                 update(1,1,n,u+tep,v,0);
    110             }
    111         }
    112     }
    113 }












  • 相关阅读:
    js将UTC时间转化为当地时区时间 用JS将指定时间转化成用户当地时区的时间
    elementUI里面,用tabs组件导致浏览器卡死的问题
    根据数组对象中的属性值删除对象
    js货币金额正则表达式
    vue elementui input不能输入的问题
    vue+elementui--$message提示框被dialog遮罩层挡住问题解决
    Oracle日期函数
    plsql查询报错:Dynamic Performamnce Tables not accessible
    Oracle rownum和rowid的区别
    Oracle通过序列实现主键自增长
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10959004.html
Copyright © 2020-2023  润新知