给出一堆括号让你判断其能否匹配,这应该是一道很水的模拟进出栈的题。现在给出模板代码:
var s:ansistring; i,j,top,n:longint; flag:boolean; a:array[0..1000001]of longint; function fct(x:char):longint; begin case x of '<':exit(1); '>':exit(1); '(':exit(2); ')':exit(2); '[':exit(3); ']':exit(3); '{':exit(4); '}':exit(4); end; end; begin readln(n);//有n组数据 for j:=1 to n do begin a[0]:=5; flag:=true; readln(s);//读入的括号序列 top:=0; for i:=1 to length(s) do begin if s[i]='<' then begin inc(top);a[top]:=fct('<'); if a[top]>a[top-1] then flag:=false; end; if s[i]='(' then begin inc(top);a[top]:=fct('('); if a[top]>a[top-1] then flag:=false; end; if s[i]='[' then begin inc(top);a[top]:=fct('['); if a[top]>a[top-1] then flag:=false; end; if s[i]='{' then begin inc(top);a[top]:=fct('{'); if a[top]>a[top-1] then flag:=false; end;//都是左括号,进栈 if (s[i]='>')or(s[i]=')')or(s[i]=']')or(s[i]='}') then if a[top]=fct(s[i]) then dec(top) else flag:=false;//右括号出栈 if top<0 then flag:=false; if not flag then break; end; if top<>0 then flag:=false; if flag then writeln('YES') else writeln('NO'); end; end.在完全理解上面的代码之后,你就可以向下看了。 PS:其实下面的内容和上面并没有什么关系。。。
序列统计 【题目描述】 一个有N个数的数列A(初始时全部为0),并给出M个操作,每个操作给出两个整数l和r,把[l,r]里的数全部加1,最后输出这个序列。 1<=N<=1000000 1<=M<=1000000 【分析】 根据数据范围就可以看出,按照题目的描述去模拟的方法显然会超时。于是我们选用一种叫做差分的技巧(其实还有很多其他的方法,不过这种方法的代码应该最短)求解。如果把此题看成括号匹配,就是说l是左括号,r是右括号,然后打标记——在A[l]上打上+1,在A[r+1]上打上-1。然后一个循环扫描一遍,记录当前经过的标签之和(+1就是加1,-1就是减1)就可以了。 光是语言描述可能不太清楚,下面举个例子:有5个数,操作给出l=2,r=4。 初始:0 0 0 0 0 标记:0 1 0 0 -1 扫描:0 1 1 1 0 看,是不是A[2]~A[4]都变成了1! 这样对于每个操作只要O(1)的时间打标记,最后一重循环统计即可,总时间复杂度O(M+N)。
矩阵统计 【题目描述】 给出一个N*N的矩阵A,初始时全部为0。并给出M个操作,每个操作给出四个整数x1,y1,x2,y2,表示把A[x1,y1]~A[x2,y2]中的所有数都加上1。最后输出整个矩阵。 1<=N<=1000 1<=M<=1000000 【分析】 就是比上一题增加了一个维度,仍然可以用一维的方法来做,不过打标记的方法变了——在A[x1..x2,y1]中打上+1,在A[x1..x2,y2+1]中打上-1,最后的每一行都按照一维方法操作即可。
#include<cstdio> int f[1010][1010]={0},sum[1010][1010]; int main() { int n,m,x1,y1,x2,y2; scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); for (int j=x1;j<=x2;j++) { f[j][y1]+=1;f[j][y2+1]-=1; } } for (int i=1;i<=n;i++) { int t=0; for (int j=1;j<=n;j++) { t+=f[i][j]; sum[i][j]=t; } } for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) printf("%d ",sum[i][j]); printf("\n"); } return 0; }校门外的树 【题目描述】 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。 由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。 1<=L<=1000000 1<=区域数量<=1000000 【分析】 用数组模拟的方法自然是过不了的,于是我们想到了差分。注意上面的算法都是把某个区间加1,而此题是减1。而且最后输出的不是马路的情况,而是树的数量,所以在最后扫描的时候要略作改动。
var i,n,m,x,y:longint; f:array[0..100000001]of shortint; begin readln(n,m); fillchar(f,sizeof(f),0); for i:=1 to m do begin readln(x,y); inc(f[x]);dec(f[y+1]); end; x:=0; y:=0; for i:=0 to n do begin inc(x,f[i]); if x=0 then inc(y); end; writeln(y); end.转载于:https://www.cnblogs.com/JRX2015U43/p/6533521.html
相关资源:差分匹配电路设计