我的代码不知为什么t掉了,这个等杰少回来再去问问他
先把我t掉的代码放在这里,主要是学一下动态建树的思想
这个是非常省空间的
这题目主要思路就是对每个颜色建一颗线段树,保存其y1,y2,范围内的点到y轴的最小距离
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
struct Tree
{
int l,r,val;
};
Tree tree[4001000];
int cnt,Root[56];
void update(int&root,int val,int poi,int l,int r)
{
if (root==-1)
{root=cnt;cnt++;}
if (l==r)
{tree[root].val=min(val,tree[root].val);tree[root].l=tree[root].r=-1;return;}
int mid=(l+r)/2;
if (poi<=mid)
{
update(tree[root].l,val,poi,l,mid);
if (tree[root].r==-1)
tree[root].val=tree[tree[root].l].val;
else
tree[root].val=min(tree[tree[root].l].val,tree[tree[root].r].val);
}
else
{
update(tree[root].r,val,poi,mid+1,r);
if (tree[root].l==-1)
tree[root].val=tree[tree[root].r].val;
else
tree[root].val=min(tree[tree[root].l].val,tree[tree[root].r].val);
}
return;
}
int query(int root,int ql,int qr,int l,int r)
{
if (root==-1) return inf;
if (ql>r||qr<l) return inf;
if (ql<=l&&qr>=r)
return tree[root].val;
int mid=(l+r)/2;
return min(query(tree[root].r,ql,qr,mid+1,r),query(tree[root].l,ql,qr,l,mid));
}
void init()
{
cnt=1;
memset(Root,-1,sizeof(Root));
for (int k=0 ;k<4000100;k++)
{tree[k].l=tree[k].r=-1;tree[k].val=inf;}
return;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
if (n==0)
{
init();
}
else if (n==1)
{
int x,y,c;
scanf("%d %d %d",&x,&y,&c);
update(Root[c],x,y,1,1000000);
}
else if (n==2)
{
int x,y1,y2;
scanf("%d %d %d",&x,&y1,&y2);
if (y1>y2)
{y1^=y2;y2^=y1;y1^=y2;}
int cou(0);
for (int k=0;k<=50;k++)
{
if (query(Root[k],y1,y2,1,1000000)<=x)
{cou++;}
}
printf("%d\n",cou);
}
else return 0;
}
return 0;
}
在杰少的帮助下终于过了,原来是我的线段树写的丑了点
最怕卡常数的题目
现在附上ac代码,两个代码只有query函数不同
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
struct Tree
{
int l,r,val;
};
Tree tree[4001000];
int cnt,Root[56];
void update(int&root,int val,int poi,int l,int r)
{
if (root==-1)
{root=cnt;cnt++;}
if (l==r)
{tree[root].val=min(val,tree[root].val);tree[root].l=tree[root].r=-1;return;}
int mid=(l+r)/2;
if (poi<=mid)
{
update(tree[root].l,val,poi,l,mid);
if (tree[root].r==-1)
tree[root].val=tree[tree[root].l].val;
else
tree[root].val=min(tree[tree[root].l].val,tree[tree[root].r].val);
}
else
{
update(tree[root].r,val,poi,mid+1,r);
if (tree[root].l==-1)
tree[root].val=tree[tree[root].r].val;
else
tree[root].val=min(tree[tree[root].l].val,tree[tree[root].r].val);
}
return;
}
int query(int root,int ql,int qr,int l,int r)
{
if (root==-1) return inf;
// if (ql>r||qr<l) return inf;
//
// if (ql<=l&&qr>=r)
// return tree[root].val;
if(l == ql && r == qr) return tree[root].val;
int mid=(l+r)/2;
if(qr <= mid) return query(tree[root].l,ql,qr,l,mid);
else if(ql >= mid + 1) return query(tree[root].r,ql,qr,mid+1,r);
return min(query(tree[root].l,ql,mid,l,mid), query(tree[root].r,mid + 1,qr,mid + 1,r));
}
void init()
{
cnt=1;
memset(Root,-1,sizeof(Root));
for (int k=0 ;k<4000100;k++)
{tree[k].l=tree[k].r=-1;tree[k].val=inf;}
return;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
if (n==0)
{
init();
}
else if (n==1)
{
int x,y,c;
scanf("%d %d %d",&x,&y,&c);
update(Root[c],x,y,1,1000000);
}
else if (n==2)
{
int x,y1,y2;
scanf("%d %d %d",&x,&y1,&y2);
if (y1>y2)
{y1^=y2;y2^=y1;y1^=y2;}
int cou(0);
for (int k=0;k<=50;k++)
{
if (query(Root[k],y1,y2,1,1000000)<=x)
{cou++;}
}
printf("%d\n",cou);
}
else return 0;
}
return 0;
}
总结一下,如果要建多个线段树的话就开一个结构体,tree然后树上的每个节点都可以用这个结构体来存
然后对于第i个树,我们要找他的话就只要找到根节点就行了也就是root[i]