• [cf896E]Welcome home, Chtholly


    将序列分块,对每一个块维护以下信息:

    1.块内的最大值$\max$和区间减的懒标记

    2.存在的权值(包含即可)以及对应元素的链表(首尾、长度)

    对于散块修改/询问,可以利用2重构序列,即可$o(\sqrt{n})$修改/询问

    对于整块修改,注意到最大值单调不降,因此在$o(\Delta \max)$的复杂度内实现即可

    具体的,对于$x$和$\max$的关系分类讨论:

    1.若$\max\le x$,显然操作无意义

    2.若$\max \le 2x$,将$(x,\max]$对应的链表起点重新记录,并重算最大值(不断减小)

    3.若$2x<\max $,通过区间减的懒标记,变为将$[1,x]$中的元素加$x$,进而做法类似2

    对于整块查询,利用2对应的长度信息即可

    时间复杂度为$o(n+V\sqrt{n}+m\sqrt{n})$(其中$V$为值域),可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100005
      4 #define M 350
      5 vector<int>v[M];
      6 int n,m,K,p,l,r,x,ans,a[N],bl[N],st[M],ed[M],mx[M],tag[M],nex[N];
      7 struct Link{
      8     int h,t,len;
      9     Link(){
     10         h=t=len=0;
     11     }
     12     bool empty(){
     13         return !len;
     14     }
     15     void add(int k){
     16         if (empty())h=k;
     17         else nex[t]=k;
     18         t=k,len++;
     19     }
     20     void add(Link k){
     21         if (k.empty())return;
     22         if (empty())h=k.h;
     23         else nex[t]=k.h;
     24         t=k.t,len+=k.len;
     25     }
     26 }L[M][N];
     27 void build_a(int k){
     28     for(int i=0;i<v[k].size();i++){
     29         if (L[k][v[k][i]].empty())continue;
     30         for(int j=L[k][v[k][i]].h;;j=nex[j]){
     31             a[j]=v[k][i];
     32             if (j==L[k][v[k][i]].t)break;
     33         }
     34         L[k][v[k][i]]=Link();
     35     }
     36     for(int i=st[k];i<=ed[k];i++)a[i]-=tag[k],nex[i]=0;
     37     mx[k]=tag[k]=0,v[k].clear();
     38 }
     39 void build_info(int k){
     40     for(int i=st[k];i<=ed[k];i++){
     41         mx[k]=max(mx[k],a[i]);
     42         v[k].push_back(a[i]),L[k][a[i]].add(i);
     43     }
     44 }
     45 void update(int l,int r,int x){
     46     build_a(bl[l]);
     47     for(int i=l;i<=r;i++)
     48         if (a[i]>x)a[i]-=x;
     49     build_info(bl[l]);
     50 }
     51 void update(int k,int x){
     52     if (mx[k]<=x)return;
     53     if (mx[k]<=(x<<1)){
     54         for(int i=x+tag[k]+1;i<=mx[k]+tag[k];i++)
     55             if (!L[k][i].empty()){
     56                 if (L[k][i-x].empty())v[k].push_back(i-x);
     57                 L[k][i-x].add(L[k][i]),L[k][i]=Link();
     58             }
     59         while (L[k][mx[k]+tag[k]].empty())mx[k]--;
     60         return;
     61     }
     62     for(int i=tag[k]+1;i<=x+tag[k];i++)
     63         if (!L[k][i].empty()){
     64             if (L[k][i+x].empty())v[k].push_back(i+x);
     65             L[k][i+x].add(L[k][i]),L[k][i]=Link();
     66         }
     67     tag[k]+=x,mx[k]-=x;
     68 }
     69 int query(int l,int r,int x){
     70     build_a(bl[l]),build_info(bl[l]);
     71     int ans=0;
     72     for(int i=l;i<=r;i++)
     73         if (a[i]-tag[bl[l]]==x)ans++;
     74     return ans;
     75 }
     76 int query(int k,int x){
     77     if (x+tag[k]>=N)return 0;
     78     return L[k][x+tag[k]].len;
     79 }
     80 int main(){
     81     scanf("%d%d",&n,&m),K=(int)sqrt(n);
     82     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
     83     for(int i=1;i<=n;i++)bl[i]=(i-1)/K+1;
     84     for(int i=1;i<=bl[n];i++){
     85         st[i]=(i-1)*K+1,ed[i]=min(i*K,n);
     86         build_info(i);
     87     }
     88     for(int i=1;i<=m;i++){
     89         scanf("%d%d%d%d",&p,&l,&r,&x);
     90         if (p==1){
     91             if (bl[l]==bl[r])update(l,r,x);
     92             else{
     93                 update(l,ed[bl[l]],x),update(st[bl[r]],r,x);
     94                 for(int j=bl[l]+1;j<bl[r];j++)update(j,x);
     95             }
     96         }
     97         if (p==2){
     98             if (bl[l]==bl[r])ans=query(l,r,x);
     99             else{
    100                 ans=query(l,ed[bl[l]],x)+query(st[bl[r]],r,x);
    101                 for(int j=bl[l]+1;j<bl[r];j++)ans+=query(j,x);
    102             }
    103             printf("%d\n",ans);
    104         }
    105     }
    106     return 0;
    107 } 
    View Code
  • 相关阅读:
    listview 选择后高亮显示
    高德坐标转百度坐标并导航
    android scrollview listview显示不全
    java.lang.UnsatisfiedLinkError: Couldn't load vi_voslib from loader dalvik.system.PathClassLoader
    JAVA Map 和 List 排序方法
    Butter Knife 使用方法
    Volley 结合GSON或FastJson用法
    android-menudrawer 和SlidingMenu 用法
    ueditor 正在读取目录及网络链接错误
    【449】backup get weekly tweets
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/16026154.html
Copyright © 2020-2023  润新知