数列分块入门1
题目描述
给出一个长为 n 的数列,以及 n 个操作,操作涉及区间加法,单点查值。
第一行输入一个数字 n。
第二行输入 n 个数字,第 i个数字为 ai,以空格隔开。
接下来输入 n 行询问,每行输入四个数字 opt、l、r、c,以空格隔开。
若 opt=0,表示将位于 [l,r]的之间的数字都加 c。
若 opt=1,表示询问 ar的值(l 和 c 忽略)
Solution:
我们给每个块设置一个加法标记(就是记录这个块中元素一起加了多少),每次操作对每个整块直接O(1)标记,而不完整的块由于元素比较少,暴力修改元素的值。
每次询问时返回元素的值加上其所在块的加法标记。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 50000 + 10; const int M = 225; inline int read() { char ch; int fl=1; int x=0; do{ ch= getchar(); if(ch=='-') fl=-1; }while(ch<'0'||ch>'9'); do{ x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); }while(ch>='0'&&ch<='9'); return x*fl; } ll n; ll a[MAXN]; ll opt,c,l,r; ll now,ks; ll add[M+10]; int main() { n = read(); ks=1; now=0; for(int i=1;i<=n;i++) { a[i] = read(); } for(int i=1;i<=n;i++) { opt = read();l=read();r=read();c=read(); if(opt==0) { if((l-1)/M+1!=(r-1)/M+1) { for(int j=l;j<=((l-1)/M+1)*M;j++) a[j]+=c; for(int j=(l-1)/M+2;j<=(r-1)/M;j++) add[j]+=c; for(int j=((r-1)/M)*M+1;j<=r;j++) a[j]+=c; } else { for(int j=l;j<=r;j++) a[j]+=c; } } if(opt==1) { printf("%lld ",a[r]+add[(r-1)/M+1]); } } }
数列分块入门2
题目描述
给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内小于某个值x的元素个数。
solution:
考虑把原数列分成sqrt(n)块,每块维护一个有序的序列。
首先考虑加法操作:对于整块的直接维护加法标记,不是整块的暴力修改元素,然后对块内元素重排。
然后考虑查询:对于整块的由于块内元素有序,可以直接二分。对于不是整块的暴力统计。
然而我以前写的代码WA了,加上最近没时间改,所以就不放代码了。
数列分块入门3
题目描述
给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内比某个值x其小的最大元素。
Solution:
只有查询和2不一样,那改一下二分就行了QAQ
数列分块入门4
题目描述
一个长为n的数列,以及n个操作,操作涉及区间加法,区间求和
solution:
分块后维护元素和,对于整块维护一个add标记
数列分块入门9
题目描述
给出一个长为 n 的数列,以及 n 个操作,操作涉及区间众数。
solution:
不会,主席树暴力拿了一个LOJ rank1,又短又好写。(现在不是了)
代码如下:
#include<bits/stdc++.h> #pragma GCC optimize(2) #pragma GCC optimize(3) using namespace std; inline char nc() { static char buf[1000000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++; } inline int read() { char ch; int fl=1; int x=0; do{ ch= nc(); if(ch=='-') fl=-1; }while(ch<'0'||ch>'9'); do{ x=(x<<3)+(x<<1)+ch-'0'; ch=nc(); }while(ch>='0'&&ch<='9'); return x*fl; } const int MAXN = 100000+10; struct p_tree { int sum; int lcc; int rcc; } ; p_tree t[MAXN*25]; int root[MAXN],cnt=0; struct node { int val; int id; friend bool operator < (node a1,node a2) { return a1.val<a2.val; } }; node a[MAXN]; int c[MAXN]; int zsi,zsz; bool bz; int ck; inline void update(int& rt,int x,int k,int l,int r) { t[++cnt]=t[rt]; rt = cnt; t[rt].sum+=k; if(l==r) return; int mid=(l+r)>>1; if(x<=mid) update(t[rt].lcc,x,k,l,mid); else update(t[rt].rcc,x,k,mid+1,r); } inline void query(int l,int r,int x,int y) { if(bz) return; if(x==y) { if(zsz<t[r].sum-t[l].sum) { zsz=t[r].sum-t[l].sum; zsi=x; } if(zsz>(ck)/2) { bz = true; } return; } else { if(zsz<t[t[r].lcc].sum-t[t[l].lcc].sum) { query(t[l].lcc,t[r].lcc,x,(x+y)>>1); } if(zsz<t[t[r].rcc].sum-t[t[l].rcc].sum) { query(t[l].rcc,t[r].rcc,((x+y)>>1)+1,y); } } } int n,q; int rankk[MAXN]; int main() { n=read(); for(register int i=1;i<=n;i++) a[i].val=read(),a[i].id=i;; root[0]=0; t[0].sum=t[0].lcc=t[0].rcc=0; sort(a+1,a+n+1); int top=0; for(register int i=1;i<=n;i++) { if(a[i].val!=a[i-1].val) top++; c[a[i].id]=top; rankk[top]=a[i].val; } for(register int i=1;i<=n;i++) { root[i]=root[i-1]; update(root[i],c[i],1,1,100000); } zsi=0,zsz=0; for(register int i=1;i<=n;i++) { bz = false; int u=read(),v=read(); if(u>v) swap(u,v); ck = v-u+1; zsi = 0,zsz = 0; query(root[u-1],root[v],1,100000); printf("%d ",rankk[zsi]); } }
我暴力似乎碾标算了。。。291ms