前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >牛客寒假算法基础集训营5 E. 炫酷划线(树状数组)

牛客寒假算法基础集训营5 E. 炫酷划线(树状数组)

作者头像
Ch_Zaqdt
发布2019-03-05 11:02:09
3530
发布2019-03-05 11:02:09
举报
文章被收录于专栏:Zaqdt_ACMZaqdt_ACM

题目链接:https://ac.nowcoder.com/acm/contest/331/E

       这道题在纸上画一画就会发现其实是一个区间覆盖的问题,实际上问的是第几个区间会第一次出现区间相交的情况。首先来看一下数据范围,T组数据,n和m都是100000,但是题目中说了一个点只能连一次,所以边最多有50000个,但是如果暴力的话,时间复杂度依然是50000*50000*10,显然过不了,但是在比赛的时候水了一发,竟然过了....(赛后数据加强了,就把暴力的做法卡了)。

       这道题的思路其实和暴力的思路差不多,但是用树状数组去做会更巧妙一点,做法就是插点问线,顾名思义就是我们对每一个区间的左端点和右端点进行标记,然后在每次询问的时候判断这个区间内的值是否为0,如果不为0就说明出现了相交的情况。标记的方法是对每一个区间的左端点+i,右端点-i(i为第i个区间),需要注意的是每个区间用来标记的数必须不同,不能是每个左端点加1,右端点减1这样,自己画画图就知道为什么了...


AC代码:

代码语言:javascript
复制
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
int pre[maxn];
int T,n,m;

int lowbit(int x){
  return x & (-x);
}

void Update(int x,int y){
  for(int i=x;i<=n;i+=lowbit(i)){
    pre[i] += y;
  }
}

int Query(int x){
  int sum = 0;
  for(int i=x;i>=1;i-=lowbit(i)){
    sum += pre[i];
  }
  return sum;
}

int main()
{
  scanf("%d",&T);
  while(T--){
    memset(pre, 0, sizeof(pre));
    bool flag = false;
    scanf("%d%d",&n,&m);
    int pos = -1;
    for(int i=1;i<=m;i++){
      int l, r;
      scanf("%d%d",&l, &r);
      if(l > r) swap(l, r);
      if(flag == false){
        int xx = Query(l - 1);
        int yy = Query(r);
        if(yy - xx != 0){
          pos = i;
          flag = true;
        }
        else{
          Update(l, i);
          Update(r, -i);
        }
      }
    }
    printf("%d\n", pos);
  }
  return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年02月01日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档