今天都是看的线段树,终于自己能编出简单的来了,虽然还没弄明天离散化,但是先放着,怕文件丢了,先上传再说。
在睡前终于把代码都敲出没有问题出来了,哎哟,累了一天了,继续努力,争取这两天把离散化也学会了!!!
未离散化,也没lazy标记,所以只有在数据比较少的时候才能通过,不然就TLE了。离散化和lazy标记提交通过的代码在下下章!
下面是入门敲的代码,一点一点把线段树的本质搞定。弄明白了线段树是怎么运作的。
#include <iostream> #include <map> #include <deque> #include <vector> #include <queue> #include <stack> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <set> using namespace std; int INF=1<<30; const int m=100000; //本来不想离散化了,自己也还没搞定明白离散化,所以相把m开到10^9,但是太大了不行,所以还是学离散化吧 struct node { int a,b,sum; }tree[m*5]; void build(int now,int a,int b) { tree[now].a=a; tree[now].b=b; tree[now].sum=0; //建立完全二叉树,因为每个点可能都要用得到,其实理解最好的方法是看图再理解代码最快 if(a==b) return; int mid=(a+b)>>1; build(now*2,a,mid); build(now*2+1,mid+1,b); } void update(int i,int a,int b) { if(tree[i].a==a&&tree[i].b==b) { tree[i].sum++; if(tree[i].a==tree[i].b) return; update(i*2,a,(a+b)/2); //找到这条线段之后,这条线段以下的所以儿子都要更新,以使最后的点有,我设这个点为(x,x)即左右端点都相等表示这个点 update(i*2+1,(a+b)/2+1,b); return; } int mid=(tree[i].a+tree[i].b)/2; if(a<=mid) update(i*2,a,min(mid,b)); //找到这条线段为此 if(b>mid) update(i*2+1,max(a,mid+1),b); } int query(int i,int x) { int mid=(tree[i].a+tree[i].b)>>1; if(tree[i].a==x&&tree[i].b==x) return tree[i].sum; //上面说过,左右端点相等表示这个点 if(x<=mid) return query(i*2,x); else return query(i*2+1,x); } int main() { int t,p,k=1,n,m,i,c,d; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); build(1,1,10000); //建树 for(i=0;i<n;i++) { scanf("%d%d",&c,&d); update(1,c,d); //更新树 } printf("Case #%d:\n",k++); for(i=0;i<m;i++) { scanf("%d",&p); printf("%d\n",query(1,p)); //查询 } } return 0; }