zoukankan      html  css  js  c++  java
  • 一维差分

      比赛时遇见了个二维差分,很可惜没看出来,还想用线段树维护,wtcl。痛心之余,回来补一补差分。

      差分一般用来解决区间操作,而区间操作当然可以用线段树写,但相比较下,差分更好实现而且更快,不过差分只能处理离线问题,不能一边更新一边查询。

      差分的思想很简单,我们要在一个区间[l,r]内都加上一个数a,那么像树状数组去区间更新一样,我们弄一个差分数组,在dif[l]处+a,在dif[r+1]处-a,这样像前缀和一样扫过l到r这个区间时,在l处开始有+a,+a对[l,r]区间产生影响,在r+1处-a变回原来的值,对r+1后面的区间没有了影响

    Color the ball HDU - 1556 

      题目大意:n个点,n次操作,每次对一个区间涂色,最后问每个点被涂了多少次。

     1 #include<cstdio>
     2 const int N=100118;
     3 int cov[N],l,r;
     4 int main()
     5 {
     6     int n;
     7     while(scanf("%d",&n)&&n)
     8     {
     9         for(int i=1;i<=n;i++)
    10             cov[i]=0;
    11         for(int i=1;i<=n;i++)
    12         {
    13             scanf("%d%d",&l,&r);
    14             cov[l]++;
    15             cov[r+1]--;
    16         }
    17         for(int i=1;i<=n;i++)
    18         {
    19             if(i>1)
    20                 printf(" ");
    21             cov[i]+=cov[i-1];
    22             printf("%d",cov[i]);
    23         }
    24         printf("
    ");
    25     }
    26     return 0; 
    27 } 
    气球涂呀涂

    Tallest Cow POJ - 3263 

      题目大意:n头牛,第i处的牛最高为h有r组关系,每组一个a,b意味着a能看到b,即a和b中间的都严格低于a和b,问每个牛最高的可能高度。

      我们假设每个牛一开始都是最高的高度h,那么每组a,b关系其实就是[a+1,b-1]处的牛高度都减1。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<map>
     4 using namespace std;
     5 const int N=11108;
     6 int high[N];
     7 map<int,int> m;
     8 inline void init(int n)
     9 {
    10     m.clear();
    11     for(int i=1;i<=n;i++)
    12         high[i]=0;
    13 }
    14 int main()
    15 {
    16     int n,pos,maxh,r,a,b;
    17     while(~scanf("%d%d%d%d",&n,&pos,&maxh,&r))
    18     {
    19         init(n); 
    20         while(r--)
    21         {
    22             scanf("%d%d",&a,&b);
    23             if(a>b)
    24                 swap(a,b);
    25             if(b-a<=1||m[a*n+b])//map去重边 
    26                 continue;
    27             m[a*n+b]=1;
    28             high[a+1]--;
    29             high[b]++;
    30         }
    31         for(int i=1;i<=n;i++)
    32         {
    33             high[i]+=high[i-1];
    34             printf("%d
    ",high[i]+maxh);
    35         }
    36     }
    37     return 0;
    38 }
    太牛了

    牛客练习赛34little w and Segment Coverage

      题目大意:有n个点,有m个区间,问如果去掉其中一个区间没被任意区间覆盖的点最少有多少个,已经相应的区间编号,多个符合要求的区间输出最大编号的。

      先差分处理得出每个点被多少个区间覆盖,然后记录没被覆盖的点,以及维护只被覆盖一次的点的数目的前缀和,那么去掉某个区间后,没被覆盖的点就sum[r]-sum[l-1]+原先就没被覆盖的点

     1 #include<cstdio>
     2 const int N=1000118;
     3 int cov[N],sum[N]={0},l[N],r[N];
     4 //cov记录差分值,sum表示只被一个区间覆盖的点个数的前缀和 
     5 int main()
     6 {
     7     int n,m;
     8     scanf("%d%d",&n,&m);
     9     for(int i=1;i<=m;i++)
    10     {
    11         scanf("%d%d",&l[i],&r[i]);
    12         cov[l[i]]++;
    13         cov[r[i]+1]--;
    14     }
    15     int no=0;//no记录没被区间覆盖的点 
    16     for(int i=1;i<=n;i++) 
    17     {
    18         cov[i]+=cov[i-1];
    19         if(cov[i]==0)
    20             no++;
    21         //因为题目要求去掉一个区间后,剩余没被覆盖的点,
    22         //所以统计只被一个区间覆盖的点的前缀和 
    23         if(cov[i]==1)
    24             sum[i]=1;
    25         else
    26             sum[i]=0;
    27         sum[i]+=sum[i-1];
    28     }
    29     int id=1,len=n+1;
    30     for(int i=1;i<=m;i++)
    31     {
    32         int dis=sum[r[i]]-sum[l[i]-1];
    33         if(dis<=len)
    34             id=i,len=dis;
    35     }
    36     printf("%d %d
    ",id,len+no); 
    37     return 0; 
    38 } 
    牛客也很牛
  • 相关阅读:
    关于java.lang.reflect.InvocationTargetException
    Java并发编程(三)后台线程(Daemon Thread)
    Lab 7-2
    Lab 7-1
    Lab 6-3
    Lab 6-2
    Lab 6-1
    Lab 5-1
    Lab 3-4
    Lab 3-3
  • 原文地址:https://www.cnblogs.com/LMCC1108/p/10742972.html
Copyright © 2011-2022 走看看