HDU1828 Picture

痛定思痛。 2023-01-11 09:24 201阅读 0赞

-———————————

扫描线求周长

链接(HDU):Miku

链接(Vjudge):Miku

-———————————

HDU是多组数据!!!而且不写明白了!!!

我本以为既然多组数据,何不写上一共几组,既然不写,那必然是不存在了

但是它就是多组数据

-——————————-

这道题显然的做法是扫描两次,横着一次竖着一次,不过会很繁琐

事实上,一次就够了

-———————————

完全可以从上向下扫描一次,对于竖线,显然就是两条线段之间的高度*区间个数*2(更新前)

而对于横线,就是两次的区间长度之差的绝对值(因为无论是+还是-,裸露出来的就是变化的长度)
-————————————

这样就变成了两个小问题了

横线的求法,没有特别之处,但是竖线,因为是求区间线段数,就要特别处理一下了

我用了额外两个数组,ld,rd,代表一个区间的左右端点是否被覆盖,显然左端点就是左儿子左端点,右端点同理

但是如果左右儿子连起来了,还要特判

所以pushup更长了

  1. void pushup(int x,int l,int r){
  2. if(lazy[x]>=1){
  3. sum[x]=r-l+1;
  4. summ[x]=2;
  5. ld[x]=rd[x]=1;
  6. }
  7. else if(l!=r){
  8. sum[x]=sum[x<<1]+sum[x<<1|1];
  9. ld[x]=ld[x<<1];
  10. rd[x]=rd[x<<1|1];
  11. summ[x]=summ[x<<1]+summ[x<<1|1];
  12. if(ld[x<<1|1]&&rd[x<<1]) summ[x]-=2;
  13. }
  14. else{
  15. sum[x]=0;
  16. summ[x]=0;
  17. ld[x]=0;
  18. rd[x]=0;
  19. }
  20. }

-—————————————

这样来看,整个代码也就呼之欲出了

-——————————————

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cmath>
  5. using namespace std;
  6. int xx,yy,xxx,yyy;
  7. long long ans;
  8. const int maxn=100000;
  9. int last;
  10. struct li{
  11. int l;
  12. int r;
  13. long long h;
  14. int f;
  15. }line[200005];
  16. int n;
  17. int p;
  18. int sum[4000005];
  19. bool ld[4000005],rd[4000005];
  20. int lazy[4000005];
  21. int summ[4000005];
  22. int lm;
  23. int rm;
  24. bool cmp(li x,li y){
  25. return x.h<y.h;
  26. }
  27. void pushup(int x,int l,int r){
  28. if(lazy[x]>=1){
  29. sum[x]=r-l+1;
  30. summ[x]=2;
  31. ld[x]=rd[x]=1;
  32. }
  33. else if(l!=r){
  34. sum[x]=sum[x<<1]+sum[x<<1|1];
  35. ld[x]=ld[x<<1];
  36. rd[x]=rd[x<<1|1];
  37. summ[x]=summ[x<<1]+summ[x<<1|1];
  38. if(ld[x<<1|1]&&rd[x<<1]) summ[x]-=2;
  39. }
  40. else{
  41. sum[x]=0;
  42. summ[x]=0;
  43. ld[x]=0;
  44. rd[x]=0;
  45. }
  46. }
  47. void update(int x,int l,int r,int L,int R,int d){
  48. if(L<=l&&r<=R){
  49. lazy[x]+=d;
  50. pushup(x,l,r);
  51. return ;
  52. }
  53. int mid=(l+r)>>1;
  54. if(L<=mid) update(x<<1,l,mid,L,R,d);
  55. if(R>mid) update(x<<1|1,mid+1,r,L,R,d);
  56. pushup(x,l,r);
  57. }
  58. int main(){
  59. while(~scanf("%d",&n)){
  60. cin>>n;
  61. p=0;
  62. ans=0;
  63. last=0;
  64. lm=-10000;
  65. rm=10000;
  66. for(int i=1;i<=n;++i){
  67. scanf("%d%d%d%d",&xx,&yy,&xxx,&yyy);
  68. lm=min(lm,xx);
  69. rm=max(rm,xxx);
  70. p++;
  71. line[p].l=xx;
  72. line[p].r=xxx;
  73. line[p].h=yy;
  74. line[p].f=1;
  75. p++;
  76. line[p].l=xx;
  77. line[p].r=xxx;
  78. line[p].h=yyy;
  79. line[p].f=-1;
  80. }
  81. sort(line+1,line+p+1,cmp);
  82. for(int i=1;i<=p;++i){
  83. update(1,lm,rm-1,line[i].l,line[i].r-1,line[i].f);
  84. ans+=summ[1]*(line[i+1].h-line[i].h);
  85. ans+=abs(sum[1]-last);
  86. last=sum[1];
  87. }
  88. cout<<ans;
  89. }
  90. return 0;
  91. }

不知道为啥,这份代码从左往右扫会有BUG

发表评论

表情:
评论列表 (有 0 条评论,201人围观)

还没有评论,来说两句吧...

相关阅读