• 技巧专题2(离散化、分块、数列差分化及前缀和)


    离散化

    每个元素范围很大但元素个数较少的情况。

    条件:与数字之间的相对大小有关,而与具体是多少无直接联系。离线。

    常见的应用是离散后放到数据结构里。

    感觉全是数据结构题。。。(划掉,当然还有计算几何、分块一类的)

     

    Line Painting

    一个0~1e9的区间,初始都是白的,现进行N次操作,每次将一段区间图上一种颜色。最后求连续最长的白色区间。

     

    Mayor's posters

    n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000)。求出最后还能看见多少张海报。

     

    程序自动分析

    在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。

    考虑一个约束满足问题的简化版本:假设x1,x2,x3...代表程序中出现的变量,给定n个形如xi=xj或xi≠xj的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足。例如,一个问题中的约束条件为:x1=x2,x2=x3,x3=x4,x4≠x1,这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。

    现在给出一些约束满足问题,请分别对它们进行判定。

    对于每个问题,包含若干行:
    第1行包含1个正整数n,表示该问题中需要被满足的约束条件个数。
    接下来n行,每行包括3个整数i,j,e,描述1个相等/不等的约束条件,相邻整数之间用单个空格隔开。若e=1,则该约束条件为xi=xj;若e=0,则该约束条件为xi≠xj。

    $N leq 1e5 , i,j leq 1e9$

    Ultra-QuickSort

    给一些(n个)乱序的数,让你求冒泡排序需要交换数的次数

    $ n leq 500000 , a_i leq 1e9 $

     

    图形面积

    桌面上放了N个平行于坐标轴的矩形,这N个矩形可能有互相覆盖的部分,求它们组成的图形的面积。

    $N leq 100 , |Xi|,|Yi| leq 1e8 $

    将所有的横线和竖线离散化排序,用它们将原矩形切分成一个个不重叠的小矩形,然后累计面积

    分块

    分块,就是将原序列处理成各个小块,目的是尽量地达到处理和询问之间的平衡

    常用于:原本O(1)修改O(n)查询或O(n)修改O(1)查询优化成O(sqrt(n))修改O(sqrt(n))查询,或者看起来很像线段树(树状数组)但是又不好维护的。

    有些专门卡空间的题可以用分块做(lca)。

    能用分块就尽量不用树套树。

    分块是一种思想,不一定按照序列分块,也可以按照值域分块、按照大小分块等。

    教主的魔法

    每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[LR](1≤LRN)内的英雄的身高全部加上一个整数W

    CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。

    $N leq 1e6 , Q leq 3000$

    保证每块是排好序的,查找整块直接二分查找,然后散块暴力修改。
    add标记,这样排好序之后查找的话就可以通过二分跳跃很大一部分查找

    维护队列

    小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N。

    为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少。

    当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色。但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你来寻求帮助。

    $N,M leq 1e4$

    对于每一个弹珠维护上一个弹珠的位置pre,分块,对每一块内pre排序。

    hzwer的分块入门题5

    给出一个长为n的数列,以及m个操作,操作涉及区间开方,区间求和。

      

    hzwer的分块入门题8

    给出一个长为n的数列,以及m个操作,操作涉及区间询问等于一个数c的元素,并将这个区间的所有元素改为c。

    hzwer的分块入门题9

    给出一个长为n的数列,以及m个操作,操作涉及询问区间的最小众数。

    陈立杰区间众数解题报告:http://www.docin.com/p-679227660.html

    大致思路:

    如果不带修改:

    1、定理  $mode(A cup B) in mode(A) cup B$

    2、基础算法

    将数列分成sqrt(n)个块,预处理f[i][j]为从第i个块到第j个块的众数

    对于询问的区间[l,r],如果l属于第a块,r属于第b块,a!=b。

    那么把[l,r]分成3部分,1:l~a块最后一个; 2:a+1块~b-1块; 3:b块第一个~r

    第2部分已经预先处理好,我们需要对 (第2部分的众数+第1部分所有数+第3部分所有数) 中的数查询在[l,r]出现了多少次(两种方法)。

    每次询问复杂度sqrt(n)*logn,总复杂度(n+q)*sqrt(n)*logn。

    3、优化

    期望去掉log,查询一个数在[l,r]中出现次数O(1)

    预处理C[i][x]表示前i个块中x出现多少次

    预处理A[b][i][x]表示b块的前i个数中x出现多少次

    因为一个块中不同的数最多为size=sqrt(n)个,所以C、A的空间复杂度都是n*sqrt(n)的。

    对于A的处理我们还需要对每个块开一个表记录在这个块中每个数的id。

    如果带修改:

    有时间复杂度为 $ O ( (n+q) imes n^{ frac{2}{3} } ) $的算法。

    我们把序列分成$n^{frac{1}{3}}$块。同样维护每对块之间的结果。

    对于每对块之间,我们维护每个值出现了多少次和最大出现次数,同时记录出现了i次的值有多少个。

    考虑询问,方法几乎不变,仍是前面预处理的办法,修改只会对C、A中sqrt(n)个数有影响。

    Pig

    红学姐和黄学长是好朋友。有一天,黄学长想吃猪肉丸,于是他去找红学姐买猪。红学姐到她的猪圈中赶猪的时候发现有许多猪逃离了她的猪圈。

    同时红学姐发现,一个名叫wwf的魔法猪藏在某个猪圈中施法。

    为了确定wwf的位置,方老师向红学姐提出了m组询问,每次询问标号在区间[l,r]内的猪圈剩余的猪的数量和。

    猪圈中猪的数量可能是负数。

    空间限制:3M

    $n,m leq 500000,|x[i]|  leq 8000000$

    Solar Panels

    给定A,B,C,D,求满足A≤x≤B&&C≤y≤D的gcd(x,y)的最大值

    #include<iostream>
    #include<cstdio>
    using namespace std;
    void doit()
    {
        int a,b,c,d;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        a--;c--;
        int i,j,x,y,ans;
        int aa,bb,cc,dd;
        if(d>b) swap(b,d),swap(a,c);
        for(i=1;i<=d;i=j+1)
        {
            j=min(b/(b/i),d/(d/i));
            if(i<=a) j=min(j,a/(a/i));
            if(i<=c) j=min(j,c/(c/i));
            if(b/i>a/i&&d/i>c/i) ans=j;
        }
        printf("%d
    ",ans);
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--) doit();
    }
    

    [Hnoi2016]最小公倍数

    给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值。所有权值都可以分解成2^a*3^b的形式。

    现在有q个询问,每次询问给定四个参数u、v、a和b,请你求出是否存在一条顶点u到v之间的路径,使得路径依次经过的边上的权值的最小公倍数为2^a*3^b。

    注意:路径可以不是简单路径。

    $n,q leq 50000 , m leq 100000$

    把边按照a每sqrt(m)分一组,然后把询问按b排序,
    把在这组及以前的边按b排序把这些边用并查集一条一条插入并维护。
    零散的部分暴力插入并记录,做完后暴力撤销注意:并查集不能路径压缩,否则无法撤销回去

    loj6046爷

    给你一个 n 个点的有根树,1 为根,带边权,有 m 次操作。

    1 求 x 的子树中第 k 小的深度的值,如果子树中没有 k 个点则输出 -1;
    2 将 x 与 x 父亲的边权加上 k。
    保证每次操作 2 的 k 以及原树的边权小于等于一个数 len。

    如果操作 2 中 x 为 1 ,那么视为将 x 的基础深度加上了 k 。

    分块,每隔一段时间重新暴力分块,如果块大小>size或者块内极小值极大值差>S,就重分一块。
    
    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<set>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(register int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
    const int maxn=2e5+7,maxt=1000+7,maxs=2e4+7,S=2e3,INF=0x3f3f3f3f;
    int n,m,len,a[maxn],bel[maxn],sz;
    int L[maxn],R[maxn];
    
    char cc;ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    int fir[maxn],nxt[maxn],to[maxn],e=0,v[maxn];
    void add(int x,int y,int z) {
    	to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
    }
    
    int dfn[maxn],fed[maxn],dfn_clock;
    void dfs(int pos,int d) {
    	dfn[pos]=++dfn_clock;
    	a[dfn_clock]=d;
    	for(int y=fir[pos];y;y=nxt[y]) dfs(to[y],d+v[y]);
    	fed[pos]=dfn_clock;
    }
    
    int sum[maxt][maxs],pl[maxt],pr[maxt],tot;
    int d[maxn];
    
    inline void pd(int x) {
    	if(!d[x]) return;
    	For(i,L[x],R[x]) a[i]+=d[x];
    	d[x]=0;
    }
    
    inline void ud(int x) {
    	pl[x]=INF; pr[x]=-INF;
    	For(j,L[x],R[x]) {
    		pl[x]=min(pl[x],a[j]);
    		pr[x]=max(pr[x],a[j]);
    	}
    	For(j,0,pr[x]-pl[x]) sum[x][j]=0;
    	For(j,L[x],R[x]) ++sum[x][a[j]-pl[x]];
    	For(j,1,pr[x]-pl[x]) sum[x][j]+=sum[x][j-1];
    }
    
    void bld() {
    	For(i,1,tot) pd(i);
    	int now=1,ld=INF,rd=-INF; L[1]=1;
    	For(i,1,n) {
    		ld=min(ld,a[i]); rd=max(rd,a[i]);
    		if(rd-ld>S||i-L[now]>=sz) {
    			R[now]=i-1;
    			L[++now]=i;
    			ld=rd=a[i];
    		}
    		R[bel[i]=now]=i;
    	}
    	tot=now;
    	For(i,1,tot) ud(i);
    }
    
    inline int get_sum(int p,int x) {
    	if(x<pl[p]) return 0;
    	if(x>pr[p]) return sum[p][pr[p]-pl[p]];
    	return sum[p][x-pl[p]];
    }
    
    inline int q(int ld,int rd,int x) {
    	int rs=0,lt=bel[ld],rt=bel[rd];
    	if(lt==rt) {
    		For(i,ld,rd) if(a[i]<=x) ++rs;
    		return rs;
    	}
    	if(ld!=L[lt]) {For(i,ld,R[lt]) if(a[i]<=x) ++rs;}
    	else rs+=get_sum(lt,x);
    	if(rd!=R[rt]) {For(i,L[rt],rd) if(a[i]<=x) ++rs;}
    	else rs+=get_sum(rt,x);
    	For(i,lt+1,rt-1) rs+=get_sum(i,x);
    	return rs;
    }
    
    inline int Yth(int ld,int rd,int k) {
    	int lt=bel[ld],rt=bel[rd];
    	pd(lt); pd(rt);
    	if(rd-ld+1<k) return -1;
    	int l=INF,r=-INF,mid;
    	For(i,lt,rt) l=min(l,pl[i]),r=max(r,pr[i]);
    	if(l==r) return l; --l;
    	while(l<r-1) {
    		mid=(l+r)>>1;
    		if(q(ld,rd,mid)>=k) r=mid;
    		else l=mid;
    	}
    	return r;
    }
    
    inline void chge(int ld,int rd,int x) {
    	int lt=bel[ld],rt=bel[rd];
    	if(lt==rt) {
    		pd(lt); For(i,ld,rd) a[i]+=x; ud(lt);
    		return;
    	}
    	if(ld!=L[lt]) {
    		pd(lt); For(i,ld,R[lt]) a[i]+=x; ud(lt);
    	}
    	else d[lt]+=x,pl[lt]+=x,pr[lt]+=x;
    	if(rd!=R[rt]) {
    		pd(rt); For(i,L[rt],rd) a[i]+=x; ud(rt);
    	}
    	else d[rt]+=x,pl[rt]+=x,pr[rt]+=x;
    	For(i,lt+1,rt-1) d[i]+=x,pl[i]+=x,pr[i]+=x;
    }
    
    int main() {
    	read(n); read(m); read(len); sz=300;
    	int op,x,y;
    	For(i,2,n) {
    		read(x); read(y);
    		add(x,i,y);
    	}
    	dfs(1,0);
    	bld();
    	For(i,1,m) {
    		read(op); read(x); read(y);
    		if(op==1) printf("%d
    ",Yth(dfn[x],fed[x],y));
    		else chge(dfn[x],fed[x],y);
    		if(i%1000==0) bld();
    	}
    	return 0;
    }
    

      

    作诗(zuosi)

    N个数,M组询问,每次问[l,r]中有多少个数出现正偶数次。

    $n,m,c leq 1e5$

    预处理F[i][j]表示第i块到第j块的答案。
    一个询问l-r,那么中间大块x-y的答案已经得到了只要考虑l-x和y-r对答案的影响,
    对于这里面每个数统计它在x-y出现次数t1,以及l-r出现次数t2,
    根据t1,t2的奇偶性考虑其对答案的影响
    每块大小sqrt(n/logn),复杂度n sqrt(n logn)
    

      

    莫队

    适用范围:离线、查询较多、从[l,r]转移到[l-1,r]或[l+1,r]或[l,r-1]或[l,r+1]比较快(一般为O(1)或O(logn))。

    一般分为3种:普通莫队、带修莫队、树上莫队(wjx讲)。

    优雅的暴力。

    由于只维护当前状态的信息,所以空间也比较小,一般不需要维护一大堆前缀信息或者各种区间信息乱搞。

    把每个询问看作是二维平面上的点,那么我们的最小总时间,就是这些点的最小曼哈顿距离生成树, 按照这个树的顺序做,复杂度O(n*sqrt(n))

    但是为了简便一般直接分块。

    假如有2维,按照第一维分块,每块里面按照另一维排序。这个时候一般每块大小sqrt(n)较优。

    假如有3维(带修改,加上时间这一维),每块里面将第二维作为第1关键字,把第三维作为第2关键字排序。这时候一般每块大小$n^{ frac{2}{3} }$较优。

    块的最优大小根据数据的特点而改变(这就叫玄学)。

    sb题1:给出一个长为n的数列,以及m个操作,操作涉及询问区间的最小众数。不强制在线。

    sb题2:n个数,m次询问,每次问[l,r]区间有多少个数恰好出现正偶数次。不强制在线。

    Mato的文件管理

    Mato同学从各路神犇以各种方式收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号。

    Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料。他总是从文件大小从小到大看资料。

    他先把要看的文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序。

    排序程序可以在1单位时间内交换2个相邻的文件(因为加密需要,不能随机访问)。

    Mato想要使文件交换次数最小,你能告诉他每天需要交换多少次吗?

    $n,q leq 5e4$

    XOR and Favorite Number

    给你一个长度为n的数列和m个询问,问区间中多少连续子区间满足异或和为k。

    $n,m leq 1e5 , a[x] leq 1e6$

    回滚莫队:用于处理难以删除但是易于添加(其实易于删除难以添加也可以)的莫队,排序照常,

    如果左右端点在同一块直接暴力,这部分最多n sqrt n,

    否则把左端点在一块的一起处理,清空莫队,然后直接令莫队左端点在块尾,这部分n sqrtn,

    右端点照常走,这部分n sqrtn ,左端点每次走的时候记录更改了哪些量,

    走到地方记录完答案把修改回滚回去,这部分也是n sqrtn.

    历史研究

    有一个长度为N的序列。 
    有Q个询问,每次询问l~r范围内每个数值乘以该数值出现次数的最大值。

    $N leq 1e5 , Q leq 1e5 , X_i leq 1e9 $

    数列差分化及前缀和

    树状数组区间查询区间修改

    金发姑娘和N头牛

    第i头奶牛必须在指定的温度范围内A(i)..B(i)才感觉舒适(0<=A(i)<=B(i)<= 1,000,000,000)。

    如果金发姑娘在谷仓放置一个温控器;如果温度T<A(i),牛会太冷,并将产生x单位牛奶。

    如果她把恒温器调到(A(i)<=T<=B(i))这个范围内,那么牛会感到舒适,并将产生Y单位牛奶。

    如果她把恒温器调到温度T>B(i),牛会感觉很热,并将产生的Z单位牛奶。

    正如预期的那样,Y的值总是大于X和Z。给定的X,Y,和Z,以及每个牛的温度的最佳范围,如果金发姑娘设置谷仓的温控器最佳,请计算金发姑娘得到牛奶的最大数量。

    已知X,Y和Z都是整数,范围0..1000。温控器可以设置为任意整数的值。

    $N leq 2e4$

    把三个区间进行差分。把A、B离散、排序。就把问题转化成了最大前缀和问题。

    借教室

    我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借。

    共有m份订单,每份订单用三个正整数描述,分别为dj,sj,tj,表示某租借者需要从第sj天到第tj天租借教室(包括第sj天和第tj天),每天需要租借dj个教室。

    我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提供dj个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。

    借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室。

    如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。这里的无法满足指从第sj天到第tj天中有至少一天剩余的教室数量不足dj个。

    现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改订单 。

    $n,m leq 1e6$

    中位数图

    给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。

    $n leq 1e5$

    Balanced Lineup

    Farmer John 决定给他的奶牛们照一张合影,他让 N (1 ≤ N ≤ 50,000) 头奶牛站成一条直线,每头牛都有它的坐标(范围: 0..1,000,000,000)和种族(0或1)。

    他只给一部分牛照相,并且这一组牛的阵容必须是“平衡的”。平衡的阵容,指的是在一组牛中,种族0和种族1的牛的数量相等。

    请算出最广阔的区间,使这个区间内的牛阵容平衡。区间的大小为区间内最右边的牛的坐标减去最做边的牛的坐标。

    保证每个种族至少有一头牛,没有两头牛的坐标相同。

    JOIOJI

    给一个只由JOI三个字母组成的串,求最长的一个子串使其中JOI三个字母出现次数相等。

    $len leq 2e5$

    树上差分

    将路径上的所有点权值加一,求最后点的权值。找被所有路径共同覆盖的边。

    似乎noip很喜欢考。

    天天爱跑步?

    运输计划

    L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球。

    小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。

    显然,飞船驶过一条航道 是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之 间不会产生任何干扰。

    为了鼓励科技创新,L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小 P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

    在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后, 这 m 个运输计划会同时开始,所有飞船一起出发。

    当这 m 个运输计划都完成时,小 P 的 物流公司的阶段性工作就完成了。

    如果小 P 可以自由选择将哪一条航道改造成虫洞,试求出小 P 的物流公司完成阶段 性工作所需要的最短时间是多少?

    $n leq 3e5$

    大都市

    乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双向的土路,这些土路构成了一棵树。

    Blue Mary从比特堡(根)出发,需要去某个村庄,并且在两次送信经历的间隔期间,有某些土路被改造成了公路.

    请你计算出每次送信她需要走过的土路数目。

    A a b(1 <= a < b <= n),表示将a到b的土路修为公路

    W a, 则表示Blue Mary从比特堡送信到村庄a。

    保证父亲一定比儿子编号小。

    $n leq 250000$

    部落冲突

    有n个部落他们连城一棵树。处理下面三件事,所有的事件都是按照时间顺序给出的。

    1.(Q p q)从第 p 个部落出发的建筑工人想知道能否到达第 q 个部落了,你要回答的便是(Yes/No)
    2.(C p q)第 p 个部落与第 q 个部落开战了,保证他们一定是相邻的部落
    3.(U x ) 第 x 次发生的战争结束了,它将永远的被载入史册,不复存在

    $n leq 3e5$

    参考资料:

    https://www.cnblogs.com/SilverNebula/p/6035335.html

    http://blog.csdn.net/keshuai19940722/article/details/40410293

    http://blog.csdn.net/non_cease/article/details/7383736

    http://www.cnblogs.com/BeyondW/p/5908139.html

    http://hzwer.com/8053.html

    http://hzwer.com/2793.html

    http://blog.csdn.net/thy_asdf/article/details/51203421

    http://hzwer.com/3663.html

    http://www.docin.com/p-679227660.html

    http://blog.csdn.net/hzj1054689699/article/details/51866615

    https://www.cnblogs.com/Rivendell/p/4141406.html

    http://blog.csdn.net/mc_dl/article/details/78408758

    http://blog.csdn.net/MaverickFW/article/details/72988286

  • 相关阅读:
    在ASP.NET WebAPI 中使用缓存【Redis】
    Redis 缓存服务配置与使用
    使用 New Relic 监控接口服务性能 (APM)
    基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】
    svn查看代码作者的命令
    Failed to execute goal org.codehaus.mojo:rpm-maven-plugin:2.1.1:rpm (default) on project **
    Error: Cannot find a valid baseurl for repo: base
    intellij中编译报错: The packaging for this project did not assign a file to the build artifact
    fsimage 和 edits log
    查看rpm和war包内容
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/7986806.html
Copyright © 2020-2023  润新知