zoukankan      html  css  js  c++  java
  • BZOJ3734 : [Ontak2013]Miny

    将所有炸弹按坐标排序

    x<-y连边表示x爆炸了y也会爆炸

    如果是DAG则直接拓扑排序+DP求出每个点出发能走到的最左端和最右端的点

    有环则SCC缩点后再拓扑

    用线段树优化建图的过程

    边数$O(nlog n)$

    #include<cstdio>
    #include<algorithm>
    #define N 100010
    #define M 1700010
    typedef long long ll;
    struct P{ll x,r;int id;}a[N];
    inline bool cmp(P a,P b){return a.x<b.x;}
    int T,n,i,j,x,ans[N],id[N],l[N<<1],r[N<<1],tot;
    int g[3][N<<1],nxt[3][M],v[3][M],ed,f[N<<1],d[N<<1],vmin[N<<1],vmax[N<<1],q[N<<1],h,t;
    bool vis[N<<1];
    inline void min(int&a,int b){if(a>b)a=b;}
    inline void max(int&a,int b){if(a<b)a=b;}
    inline void read(ll&a){
      char c;bool f=0;a=0;
      while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
      if(c!='-')a=c-'0';else f=1;
      while(((c=getchar())>='0')&&(c<='9'))(a*=10LL)+=c-'0';
      if(f)a=-a;
    }
    inline void add(int x,int y){
      v[0][++ed]=y;nxt[0][ed]=g[0][x];g[0][x]=ed;
      v[1][ed]=x;nxt[1][ed]=g[1][y];g[1][y]=ed;
    }
    inline void ADD(int x,int y){d[y]++;v[2][++ed]=y;nxt[2][ed]=g[2][x];g[2][x]=ed;}
    void build(int a,int b){
      int x=++tot;
      vmin[x]=a,vmax[x]=b;
      if(a==b){id[a]=x;return;}
      int mid=(a+b)>>1;
      add(l[x]=tot+1,x);build(a,mid);
      add(r[x]=tot+1,x);build(mid+1,b);
    }
    void add(int x,int a,int b,int c,int d,int p){
      if(c<=a&&b<=d){add(x,p);return;}
      int mid=(a+b)>>1;
      if(c<=mid)add(l[x],a,mid,c,d,p);
      if(d>mid)add(r[x],mid+1,b,c,d,p);
    }
    inline int left(int p,ll x){
      int l=1,r=p-1,mid,t=p;
      while(l<=r)if(a[mid=(l+r)>>1].x>=x)r=(t=mid)-1;else l=mid+1;
      return t;
    }
    inline int right(int p,ll x){
      int l=p+1,r=n,mid,t=p;
      while(l<=r)if(a[mid=(l+r)>>1].x<=x)l=(t=mid)+1;else r=mid-1;
      return t;
    }
    void dfs1(int x){
      vis[x]=1;
      for(int i=g[0][x];i;i=nxt[0][i])if(!vis[v[0][i]])dfs1(v[0][i]);
      q[++t]=x;
    }
    void dfs2(int x,int y){
      vis[x]=0,f[x]=y;
      min(vmin[y],vmin[x]),max(vmax[y],vmax[x]);
      for(int i=g[1][x];i;i=nxt[1][i])if(vis[v[1][i]])dfs2(v[1][i],y);
    }
    void work(){
      for(ed=0,i=1;i<=tot;i++)g[0][i]=g[1][i]=g[2][i]=d[i]=0;tot=0;
      scanf("%d",&n);
      for(i=1;i<=n;i++)read(a[i].x),read(a[i].r),a[i].id=i;
      std::sort(a+1,a+n+1,cmp);
      build(1,n);
      for(i=1;i<=n;i++)add(1,1,n,left(i,a[i].x-a[i].r),right(i,a[i].x+a[i].r),id[i]);
      for(i=1;i<=tot;i++)vis[i]=0;
      for(t=0,i=1;i<=tot;i++)if(!vis[i])dfs1(i);
      for(i=tot;i;i--)if(vis[q[i]])dfs2(q[i],q[i]);
      for(ed=0,i=1;i<=tot;i++)for(j=g[0][i];j;j=nxt[0][j])if(f[i]!=f[v[0][j]])ADD(f[i],f[v[0][j]]);
      for(h=i=1,t=0;i<=tot;i++)if(f[i]==i&&!d[i])q[++t]=i;
      while(h<=t)for(i=g[2][x=q[h++]];i;i=nxt[2][i]){
        min(vmin[v[2][i]],vmin[x]),max(vmax[v[2][i]],vmax[x]);
        if(!(--d[v[2][i]]))q[++t]=v[2][i];
      }
      for(i=1;i<=n;i++)ans[a[i].id]=vmax[f[id[i]]]-vmin[f[id[i]]]+1;
      for(i=1;i<n;i++)printf("%d ",ans[i]);printf("%d
    ",ans[n]);
    }
    int main(){
      scanf("%d",&T);
      while(T--)work();
      return 0;
    }
    

      

  • 相关阅读:
    java面向对象之封装
    摘抄java基础
    gojs 去除水印个人总结的方法 实例为2.1版本
    引入CSS的方式,link与@import的区别
    Java 处理json字符串value中多余的双引号
    《Linux 学习》01---redis安装, 并使用Redis Desktop Manager 连接
    (二、下) springBoot 、maven 、mysql、 mybatis、 通用Mapper、lombok 简单搭建例子 《附项目源码》
    (一 、上)搭建简单的SpringBoot + java + maven + mysql + Mybatis+通用Mapper 《附项目源码》
    springBoot 官方整合的redis 使用教程:(StringRedisTemplate 方式存储 Object类型value)
    sudo命令: 在其他用户下操作root用户权限
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403213.html
Copyright © 2011-2022 走看看