zoukankan      html  css  js  c++  java
  • 线段树板子

    学习NotOnlySuccess的~~

    单点更新类(不常用)

    HDU 1166 敌兵布阵

    经典入门题

    中文题...题意略...

    数据小 可以单点更新 区间求和

     1 #define lson l, m, rt<<1
     2 #define rson m+1, r, rt<<1|1  
     3 int sum[500005];
     4 void pushup(int rt)
     5 {
     6     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
     7 }
     8 void build(int l, int r, int rt)
     9 {
    10     if(l==r)
    11     {
    12         scanf("%d", &sum[rt]);
    13         return ;
    14     }
    15     int m=(l+r)>>1;
    16     build(lson);
    17     build(rson);
    18     pushup(rt);
    19 }
    20 void update(int p, int add, int l, int r, int rt)
    21 {
    22     if(l==r)
    23     {
    24         sum[rt]+=add;
    25         return ;
    26     }
    27     int m=(l+r)>>1;
    28     if(p<=m)
    29         update(p, add, lson);
    30     else
    31         update(p, add, rson);
    32     pushup(rt);
    33 }
    34 int query(int L, int R, int l, int r, int rt)
    35 {
    36     if(L<=l && r<=R)
    37         return sum[rt];
    38     int m=(l+r)>>1;
    39     int ret=0;
    40     if(L<=m)
    41         ret+=query(L, R, lson);
    42     if(R>m)
    43         ret+=query(L, R, rson);
    44     return ret;
    45 }
    46 int main()
    47 {
    48 #ifndef ONLINE_JUDGE
    49     freopen("in.txt", "r", stdin);
    50     freopen("out.txt", "w", stdout);
    51 #endif
    52     int t, n, ca=1;
    53     int a, b;
    54     scanf("%d", &t);
    55     while(t--)
    56     {
    57         printf("Case %d:
    ", ca++);
    58         scanf("%d", &n);
    59         build(1, n, 1);
    60         char op[10];
    61         while(~scanf("%s", op))
    62         {
    63             if(strcmp(op, "End")==0)
    64                 break;
    65             scanf("%d%d", &a, &b);
    66             if(strcmp(op, "Query")==0)
    67                 printf("%d
    ", query(a, b, 1, n, 1));
    68             else if(strcmp(op, "Sub")==0)
    69                 update(a, -b, 1, n, 1);
    70             else
    71                 update(a, b, 1, n, 1);
    72         }
    73     }
    74     return 0;
    75 }
    View Code

    HDU 1754 I Hate It

    中文题...题意略...

    单点更新 区间最值

     1 #define lson l, m, rt<<1
     2 #define rson m+1, r, rt<<1|1 
     3 #define M 200005
     4 int num[M<<2];
     5 void pushup(int rt)
     6 {
     7     num[rt]=max(num[rt<<1],num[rt<<1|1]);    
     8 }
     9 void build(int l, int r, int rt)
    10 {
    11     if(l==r)
    12     {
    13         scanf("%d", &num[rt]);
    14         return ;
    15     }
    16     int m=(l+r)>>1;
    17     build(lson);
    18     build(rson);
    19     pushup(rt);
    20 }
    21 void update(int p, int ma, int l, int r, int rt)
    22 {
    23     if(l==r)
    24     {
    25         num[rt]=ma;
    26         return ;
    27     }
    28     int m=(l+r)>>1;
    29     if(p<=m)
    30         update(p, ma, lson);
    31     else 
    32         update(p, ma, rson);
    33     pushup(rt);
    34 }
    35 int query(int L, int R, int l, int r, int rt)
    36 {
    37     if(L<=l && R>=r)
    38         return num[rt];
    39     int m=(l+r)>>1;
    40     int ret=0;
    41     if(L<=m)
    42         ret=max(ret, query(L, R, lson));
    43     if(m<R)
    44         ret=max(ret, query(L, R, rson));
    45     return ret;
    46 }
    47 int main()
    48 {
    49 #ifndef ONLINE_JUDGE
    50     freopen("in.txt", "r", stdin);
    51     freopen("out.txt", "w", stdout);
    52 #endif
    53     int n, m;
    54     int a, b;
    55     char op[10];
    56     while(~scanf("%d%d", &n, &m))
    57     {
    58         build(1, n, 1);
    59         while(m--)
    60         {
    61             scanf("%s%d%d", op, &a, &b);
    62             if(strcmp(op, "Q")==0)
    63                 printf("%d
    ", query(a, b, 1, n, 1));
    64             else 
    65                 update(a, b, 1, n, 1);
    66         }
    67     }
    68     return 0;
    69 }
    View Code

    HDU 2795 Billboard

    题意:有一块h*w的板子, 要在上面贴n张1*a的海报, 要贴的尽量高, 高度相同的情况, 选择尽量靠左的。输出每张海报的高度位置. 

    每次找最大的位置 减去a即可 此题在query里面update了

    单点更新 区间最值

     1 #define M 200005
     2 #define lson l, m, rt<<1
     3 #define rson m+1, r, rt<<1|1
     4 
     5 int w;
     6 int num[M<<2];
     7 void pushup(int rt)
     8 {
     9     num[rt]=max(num[rt<<1], num[rt<<1|1]);
    10 }
    11 void build(int l, int r, int rt)
    12 {
    13     num[rt]=w;
    14     if(r==l)
    15         return ;
    16     int m=(l+r)>>1;
    17     build(lson);
    18     build(rson);
    19 }
    20 int query(int p, int l, int r, int rt)
    21 {
    22     if(l==r)
    23     {
    24         num[rt]-=p;
    25         return l;
    26     }
    27     int m=(l+r)>>1;
    28     int ret;
    29     if(p<=num[rt<<1])
    30         ret=query(p, lson);
    31     else 
    32         ret=query(p, rson);
    33     pushup(rt);
    34     return ret;
    35 }
    36 /*void update(int p, int l, int r, int rt)
    37 {
    38     if(l==r)
    39     {
    40         num[rt]-=p;
    41         return ;
    42     }
    43     int m=(l+r)>>1;
    44     if(p<=m)
    45         update(p, lson);
    46     else 
    47         update(p, rson);
    48     pushup(rt);
    49 }*/
    50 int main()
    51 {
    52 #ifndef ONLINE_JUDGE
    53     freopen("in.txt", "r", stdin);
    54     freopen("out.txt", "w", stdout);
    55 #endif
    56     int h, n, a;
    57     while(~scanf("%d%d%d", &h, &w, &n))
    58     {
    59         if(h>n)
    60             h=n;
    61         build(1, h, 1);
    62         while(n--)
    63         {
    64             scanf("%d", &a);
    65             if(a>num[1])
    66                 printf("-1
    ");
    67             else 
    68             {
    69                 printf("%d
    ",query(a, 1, h, 1));
    70             //    update(a, 1, h, 1);
    71             }
    72         }
    73     }
    74     return 0;
    75 }
    View Code

    成段更新

    HDU 1698 Just a Hook

    题意:n个钩子, 每个初始值是1, m个询问, (a, b)之间的变为c. 最后求整段和.

    由于只询问一次, 直接输出sum[1]即可, 不用query了.

     1 #define N 100005
     2 #define lson l, m, rt<<1
     3 #define rson m+1, r, rt<<1|1
     4 
     5 int col[N<<2];
     6 int sum[N<<2];
     7 void pushup(int rt)
     8 {
     9     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    10 }
    11 void pushdown(int rt, int m)
    12 {
    13     if(col[rt])
    14     {
    15         col[rt<<1]=col[rt<<1|1]=col[rt];
    16         sum[rt<<1]=(m-(m>>1))*col[rt];
    17         sum[rt<<1|1]=(m>>1)*col[rt];
    18         col[rt]=0;
    19     }
    20 }
    21 
    22 void build(int l, int r, int rt)
    23 {
    24     col[rt]=0;
    25     sum[rt]=1;
    26     if(l==r)
    27         return ;
    28     int m=(l+r)>>1;
    29     build(lson);
    30     build(rson);
    31     pushup(rt);
    32 }
    33 
    34 void update(int L, int R, int c, int l, int r, int rt)
    35 {
    36     if(L<=l && r<=R)
    37     {
    38         col[rt]=c;
    39         sum[rt]=c*(r-l+1);
    40         return ;
    41     }
    42     pushdown(rt, r-l+1);
    43     int m=(l+r)>>1;
    44     if(L<=m)
    45         update(L, R, c, lson);
    46     if(R>m)
    47         update(L, R, c, rson);
    48     pushup(rt);
    49 }
    50 
    51 int main()
    52 {
    53 #ifndef ONLINE_JUDGE
    54     freopen("in.txt", "r", stdin);
    55     freopen("out.txt", "w", stdout);
    56 #endif
    57     int t, ca=1, n, m;
    58     scanf("%d", &t);
    59     while(t--)
    60     {
    61         scanf("%d%d", &n, &m);
    62         build(1, n, 1);
    63         while(m--)
    64         {
    65             int a, b, c;
    66             scanf("%d%d%d", &a, &b, &c);
    67             update(a, b, c, 1, n, 1);
    68         }
    69         printf("Case %d: The total value of the hook is %d.
    ", ca++, sum[1]);
    70     }
    71     return 0;
    72 }
    View Code

    POJ 3468 ASimple Problem With Integers

    题意:给一个数列, 每次给(a, b)之间的加上c, 询问(a, b)的和.

    成段更新 区间求和

     1 typedef long long LL;
     2 #define N 100005
     3 #define lson l, m, rt<<1
     4 #define rson m+1, r, rt<<1|1
     5 
     6 LL col[N<<2];
     7 LL sum[N<<2];
     8 void pushup(int rt)
     9 {
    10     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    11 }
    12 void pushdown(int rt, int m)
    13 {
    14     if(col[rt])
    15     {
    16         col[rt<<1]+=col[rt];
    17         col[rt<<1|1]+=col[rt];
    18         sum[rt<<1]+=col[rt]*(m-(m>>1));
    19         sum[rt<<1|1]+=col[rt]*(m>>1);
    20         col[rt]=0;
    21     }
    22 }
    23 
    24 void build(int l, int r, int rt)
    25 {
    26     col[rt]=0;
    27     if(r==l)
    28     {
    29         scanf("%lld", &sum[rt]);
    30         return ;
    31     }
    32     int m=(l+r)>>1;
    33     build(lson);
    34     build(rson);
    35     pushup(rt);
    36 }
    37 
    38 void update(int L, int R, int c, int l, int r, int rt)
    39 {
    40     if(L<=l && r<=R)
    41     {
    42         col[rt]+=c;
    43         sum[rt]+=(LL)c*(r-l+1);
    44         return ;
    45     }
    46     pushdown(rt, r-l+1);
    47     int m=(l+r)>>1;
    48     if(L<=m)
    49         update(L, R, c, lson);
    50     if(m<R)
    51         update(L, R, c, rson);
    52     pushup(rt);
    53 }
    54 
    55 LL query(int L, int R, int l, int r, int rt)
    56 {
    57     if(L<=l && r<=R)
    58         return sum[rt];
    59     pushdown(rt, r-l+1);
    60     int m=(l+r)>>1;
    61     LL ret=0;
    62     if(L<=m)
    63         ret+=query(L, R, lson);
    64     if(m<R)
    65         ret+=query(L, R, rson);
    66     return ret;
    67 }
    68 
    69 int main()
    70 {
    71 #ifndef ONLINE_JUDGE
    72     freopen("in.txt", "r", stdin);
    73     freopen("out.txt", "w", stdout);
    74 #endif
    75     int n, q;
    76     scanf("%d%d", &n, &q);
    77     build(1, n, 1);
    78     while(q--)
    79     {
    80         char op[2];
    81         int a, b, c;
    82         scanf("%s", op);
    83         scanf("%d%d", &a, &b);
    84         if(op[0]=='Q')
    85         {
    86             printf(LLD, query(a, b, 1, n, 1));
    87             puts("");
    88         }
    89         else
    90         {
    91             scanf("%d", &c);
    92             update(a, b, c, 1, n, 1);
    93         }
    94     }
    95     return 0;
    96 }
    View Code

    上两篇NotOnlySuccess的成段更新的结题报告 (关于Hash的)

    poj2528 Mayor’s posters

    题意:在墙上贴海报, 海报可以互相覆盖, 问最后可以看见几张海报
    思路:这题数据范围很大,直接搞超时+超内存,需要离散化: 离散化简单的来说就是只取我们需要的值来用,比如说区间[1000,2000],[1990,2012]
    我们
    用不到[-∞,999][1001,1989][1991,1999][2001,2011][2013,+∞]这些值,所以我只需要1000,1990,2000,2012就够了, 将其分别映射到0,1,2,3,在于复杂度就大大的降下来了所以离散化要保存所有需要用到的值,排序后,分别映射到1~n,这样复杂度就会小很多很多而这题的难点在于每个数字其实表示的是一个单位长度(并且一个点),这样普通的离散化会造成许多错误(包括我以前的代码,poj这题数据奇弱)
    给出下面两个简单的例子应该能体现普通离散化的缺陷:
    1-10 1-4 5-10
    1-10 1-4 6-10
    为了解决这种缺陷,我们可以在排序后的数组上加些处理,比如说[1,2,6,10] 如果相邻数字间距大于1的话,在其中加上任意一个数字,比如加成[1,2,3,6,7,10],然后再做线段树就好了.
    线段树功能:update:成段替换query:简单hash

      1 #define N 10005
      2 #define lson l, m, rt<<1
      3 #define rson m+1, r, rt<<1|1
      4 
      5 int col[N<<4], x[N<<4];
      6 bool hash[N<<2];
      7 int cnt;
      8 void pushdown(int rt)
      9 {
     10     if(col[rt]!=-1)
     11     {
     12         col[rt<<1]=col[rt<<1|1]=col[rt];
     13         col[rt]=-1;
     14     }
     15 }
     16 
     17 void update(int L, int R, int c, int l, int r, int rt)
     18 {
     19     if(L<=l && r<=R)
     20     {
     21         col[rt]=c;
     22         return ;
     23     }
     24     pushdown(rt);
     25     int m=(l+r)>>1;
     26     if(L<=m)
     27         update(L, R, c, lson);
     28     if(m<R)
     29         update(L, R, c, rson);
     30 }
     31 
     32 void query(int l, int r, int rt)
     33 {
     34     if(col[rt]!=-1)
     35     {
     36         if(hash[col[rt]]==0)
     37             cnt++;
     38         hash[col[rt]]=1;
     39         return ;
     40     }
     41     if(l==r)
     42         return ;
     43     int m=(l+r)>>1;
     44     query(lson);
     45     query(rson);
     46 }
     47 
     48 int bin(int key, int n)
     49 {
     50     int l=0, r=n-1;
     51     while(l<=r)
     52     {
     53         int m=(l+r)>>1;
     54         if(x[m]==key)
     55             return m;
     56         if(x[m]<key)
     57             l=m+1;
     58         else
     59             r=m-1;
     60     }
     61     return -1;
     62 }
     63 
     64 int a[N<<2], b[N<<2];
     65 
     66 int main()
     67 {
     68 #ifndef ONLINE_JUDGE
     69     freopen("in.txt", "r", stdin);
     70     freopen("out.txt", "w", stdout);
     71 #endif
     72     int t, n;
     73     scanf("%d", &t);
     74     while(t--)
     75     {
     76         scanf("%d", &n);
     77         int  d=0;
     78         for(int i=0;i<n;i++)
     79         {
     80             scanf("%d%d", &a[i], &b[i]);
     81             x[d++]=a[i];
     82             x[d++]=b[i];
     83         }
     84         sort(x, x+d);
     85         int num=1;
     86         for(int i=1;i<d;i++)
     87             if(x[i]!=x[i-1])
     88                 x[num++]=x[i];
     89         for(int i=num-1;i>0;i--)
     90             if(x[i]!=x[i-1]+1)
     91                 x[num++]=x[i-1]+1;
     92         sort(x, x+num);
     93         fill(col, col+(N<<4), -1);
     94  //       memset(col, -1, sizeof(col));
     95         for(int i=0;i<n;i++)
     96         {
     97             int l=bin(a[i], num);
     98             int r=bin(b[i], num);
     99             update(l, r, i, 0, num-1, 1);
    100         }
    101         cnt=0;
    102         memset(hash, 0, sizeof(hash));
    103         query(0, num-1, 1);
    104         printf("%d
    ", cnt);
    105     }
    106     return 0;
    107 }
    View Code

    poj3225 Help with Intervals

    题意:区间操作, 交, 并, 补等
    思路: 我们一个一个操作来分析:(用0和1表示是否包含区间,-1表示该区间内既有包含又有不包含)
    U:把区间[l,r]覆盖成1
    I:把[-∞,l)(r,∞]覆盖成0
    D:把区间[l,r]覆盖成0
    C:把[-∞,l)(r,∞]覆盖成0 , 且[l,r]区间0/1互换
    S:[l,r]区间0/1互换
    成段覆盖的操作很简单,比较特殊的就是区间0/1互换这个操作,我们可以称之为异或操作
    很明显我们可以知道这个性质:当一个区间被覆盖后,不管之前有没有异或标记都没有意义了
    所以当一个节点得到覆盖标记时把异或标记清空
    而当一个节点得到异或标记的时候,先判断覆盖标记,如果是0或1,直接改变一下覆盖标记,不然的话改变异或标记
    开区间闭区间只要数字乘以2就可以处理(偶数表示端点,奇数表示两端点间的区间)
    线段树功能:update:成段替换,区间异或 query:简单hash

      1 #define N 100005
      2 #define lson l, m, rt<<1
      3 #define rson m+1, r, rt<<1|1
      4 const int maxn=131072;
      5 int cover[maxn<<2], Xor[maxn<<2];
      6 bool hash[maxn<<2];
      7 void pushdown(int rt)
      8 {
      9     if(cover[rt]!=-1)
     10     {
     11         cover[rt<<1]=cover[rt<<1|1]=cover[rt];
     12         Xor[rt<<1]=Xor[rt<<1|1]=0;
     13         cover[rt]=-1;
     14     }
     15     if(Xor[rt])
     16     {
     17         if(cover[rt<<1]!=-1)
     18             cover[rt<<1]^=1;
     19         else
     20             Xor[rt<<1]^=1;
     21         if(cover[rt<<1|1]!=-1)
     22             cover[rt<<1|1]^=1;
     23         else
     24             Xor[rt<<1|1]^=1;
     25         Xor[rt]=0;
     26     }
     27 }
     28 
     29 void update(char op, int L, int R, int l, int r, int rt)
     30 {
     31     if(L<=l && r<=R)
     32     {
     33         if(op=='U')
     34         {
     35             cover[rt]=1;
     36             Xor[rt]=0;
     37         }
     38         else if(op=='D')
     39         {
     40             cover[rt]=0;
     41             Xor[rt]=0;
     42         }
     43         else if(op=='C' || op=='S')
     44         {
     45             if(cover[rt]!=-1)
     46                 cover[rt]^=1;
     47             else
     48                 Xor[rt]^=1;
     49         }
     50         return ;
     51     }
     52     pushdown(rt);
     53     int m=(l+r)>>1;
     54     if(L<=m)
     55         update(op, L, R, lson);
     56     else if(op=='I' || op=='C')
     57         Xor[rt<<1]=cover[rt<<1]=0;
     58     if(m<R)
     59         update(op, L, R, rson);
     60     else if(op=='I' || op=='C')
     61         Xor[rt<<1|1]=cover[rt<<1|1]=0;
     62 }
     63 
     64 void query(int l, int r, int rt)
     65 {
     66     if(cover[rt]==1)
     67     {
     68         fill(hash+l, hash+r+1, 1);
     69         return ;
     70     }
     71     else if(cover[rt]==0)
     72         return ;
     73     pushdown(rt);
     74     int m=(l+r)>>1;
     75     query(lson);
     76     query(rson);
     77 }
     78 
     79 int main()
     80 {
     81 #ifndef ONLINE_JUDGE
     82     freopen("in.txt", "r", stdin);
     83     freopen("out.txt", "w", stdout);
     84 #endif
     85     cover[1]=Xor[1]=0;
     86     char op, l, r;
     87     int a, b;
     88     while(~scanf("%c %c%d,%d%c%*c", &op, &l, &a, &b, &r))
     89     {
     90         a<<=1, b<<=1;
     91         if(l=='(')
     92             a++;
     93         if(r==')')
     94             b--;
     95         if(a>b)
     96         {
     97             if(op=='C' || op=='I')
     98                 cover[1]=Xor[1]=0;
     99         }
    100         else
    101             update(op, a, b, 0, maxn, 1);
    102     }
    103     query(0, maxn, 1);
    104     bool flag=0;
    105     int s=-1, e;
    106     for(int i=0; i<=maxn; i++)
    107     {
    108         if(hash[i])
    109         {
    110             if(s==-1)
    111                 s=i;
    112             e=i;
    113         }
    114         else if(s!=-1)
    115         {
    116             if(flag)
    117                 printf(" ");
    118             flag=1;
    119             printf("%c%d,%d%c", s&1? '(':'[', s>>1, (e+1)>>1, e&1? ')':']');
    120             s=-1;
    121         }
    122     }
    123     if(flag==0)
    124         printf("empty set");
    125     printf("
    ");
    126     return 0;
    127 }
    View Code

    区间合并类(在pushup里合并左右儿子)

    POJ 3667 Hotel

    题意:1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
    2 a b:将[a,a+b-1]的房间清空

    区间替换 询问左端点

     1 #define lson l, m, rt<<1
     2 #define rson m+1, r, rt<<1|1
     3 
     4 int lsum[500005], msum[500005], rsum[500005];
     5 int col[500005];
     6 
     7 void pushdown(int rt, int m)
     8 {
     9     if(col[rt]!=-1)
    10     {
    11         col[rt<<1]=col[rt<<1|1]=col[rt];
    12         lsum[rt<<1]=msum[rt<<1]=rsum[rt<<1]=col[rt]? 0:m-(m>>1);
    13         lsum[rt<<1|1]=msum[rt<<1|1]=rsum[rt<<1|1]=col[rt]? 0:(m>>1);
    14         col[rt]=-1;
    15     }
    16 }
    17 void pushup(int rt, int m)
    18 {
    19     lsum[rt]=lsum[rt<<1];
    20     rsum[rt]=rsum[rt<<1|1];
    21     if(lsum[rt]==m-(m>>1))
    22         lsum[rt]+=lsum[rt<<1|1];
    23     if(rsum[rt]==(m>>1))
    24         rsum[rt]+=rsum[rt<<1];
    25     msum[rt]=max(lsum[rt<<1|1]+rsum[rt<<1], max(msum[rt<<1], msum[rt<<1|1]));
    26 }
    27 void build(int l, int r, int rt)
    28 {
    29     lsum[rt]=msum[rt]=rsum[rt]=r-l+1;
    30     col[rt]=-1;
    31     if(l==r)
    32         return ;
    33     int m=(l+r)>>1;
    34     build(lson);
    35     build(rson);
    36 }
    37 void update(int L, int R, int c, int l, int r, int rt)
    38 {
    39     if(L<=l && r<=R)
    40     {
    41         lsum[rt]=msum[rt]=rsum[rt]=c? 0: r-l+1;
    42         col[rt]=c;
    43         return ;
    44     }
    45     pushdown(rt, r-l+1);
    46     int m=(l+r)>>1;
    47     if(L<=m)
    48         update(L, R, c, lson);
    49     if(m<R)
    50         update(L, R, c, rson);
    51     pushup(rt, r-l+1);
    52 }
    53 int query(int p, int l, int r, int rt)
    54 {
    55     if(l==r)
    56         return l;
    57     pushdown(rt, r-l+1);
    58     int m=(l+r)>>1;
    59     if(msum[rt<<1]>=p)
    60         return query(p, lson);
    61     else if(lsum[rt<<1|1]+rsum[rt<<1]>=p)
    62         return m-rsum[rt<<1]+1;
    63     return query(p, rson);
    64 }
    65 int main()
    66 {
    67     int n, m, op, a, b, p;
    68     scanf("%d%d", &n, &m);
    69     build(1, n, 1);
    70     while(m--)
    71     {
    72         scanf("%d", &op);
    73         if(op==1)
    74         {
    75             scanf("%d", &a);
    76             if(msum[1]<a)
    77                 printf("0
    ");
    78             else
    79             {
    80                 p=query(a, 1, n, 1);
    81                 printf("%d
    ", p);
    82                 update(p, p+a-1, 1, 1, n, 1);
    83             }
    84         }
    85         else
    86         {
    87             scanf("%d%d", &a, &b);
    88             update(a, a+b-1, 0, 1, n, 1);
    89         }
    90     }
    91     return 0;
    92 }
    View Code
      1 const int N=50005;
      2 int lsum[N<<2], rsum[N<<2], msum[N<<2];
      3 struct node
      4 {
      5     int l, r;
      6 }segTree[N<<2];
      7 //int col[N<<2];
      8 int X[N];
      9 void pushup(int rt, int m)
     10 {
     11     lsum[rt]=lsum[rt<<1];
     12     rsum[rt]=rsum[rt<<1|1];
     13     if(lsum[rt<<1]==segTree[rt<<1].r-segTree[rt<<1].l+1)
     14         lsum[rt]+=lsum[rt<<1|1];
     15     if(rsum[rt<<1|1]==segTree[(rt<<1)|1].r-segTree[(rt<<1)|1].l+1)
     16         rsum[rt]+=rsum[rt<<1];
     17 //    if(lsum[rt]==m)
     18 //        lsum[rt]+=lsum[rt<<1|1];
     19 //    if(rsum[rt]==m)
     20 //        rsum[rt]+=rsum[rt<<1];
     21     msum[rt]=max(lsum[rt<<1|1]+rsum[rt<<1], max(msum[rt<<1], msum[rt<<1|1]));
     22 }
     23 //void pushdown(int rt, int m)
     24 //{
     25 //    if(col[rt]!=-1)
     26 //    {
     27 //        col[rt<<1]=col[rt<<1|1]=col[rt];
     28 //        lsum[rt<<1]=msum[rt<<1]=rsum[rt<<1]=col[rt]? 0:m-(m>>1);
     29 //        lsum[rt<<1|1]=msum[rt<<1|1]=rsum[rt<<1|1]=col[rt]? 0:(m>>1);
     30 //        col[rt]=-1;
     31 //    }
     32 //}
     33 void build(int l, int r, int rt)
     34 {
     35     segTree[rt].l=l;
     36     segTree[rt].r=r;
     37     lsum[rt]=rsum[rt]=msum[rt]=r-l+1;
     38 //    col[rt]=-1;
     39     if(l==r)
     40         return ;
     41     int m=(l+r)>>1;
     42     build(lson);
     43     build(rson);
     44 }
     45 void update(int p, int c, int l, int r, int rt)
     46 {
     47     if(l==r)
     48     {
     49         lsum[rt]=rsum[rt]=msum[rt]=c;
     50         return ;
     51     }
     52     int m=(l+r)>>1;
     53     if(p<=m)
     54         update(p, c, lson);
     55     else
     56         update(p, c, rson);
     57     pushup(rt, r-l+1);
     58 }
     59 int query(int p, int l, int r, int rt)
     60 {
     61     if(l==r || msum[rt]==0 || msum[rt]==r-l+1)
     62         return msum[rt];
     63 //    pushdown(rt, r-l+1);
     64     int m=(l+r)>>1;
     65     if(m>=p)
     66     {
     67 //        if(p>=(r>>1)-rsum[rt]+1)
     68         if(p>=segTree[rt<<1].r-rsum[rt<<1]+1)
     69             return query(p, lson)+query(m+1, rson);
     70         else
     71             return query(p, lson);
     72     }
     73     else
     74     {
     75 //        if(p<=(l>>1|1)+lsum[rt]-1)
     76         if(p<=segTree[(rt<<1)|1].l+lsum[rt<<1|1]-1)
     77             return query(m, lson)+query(p, rson);
     78         else
     79             return query(p, rson);
     80     }
     81 }
     82 int main()
     83 {
     84     int n, m;
     85     while(~scanf("%d%d", &n, &m))
     86     {
     87         build(1, n, 1);
     88         int d=0, a;
     89         while(m--)
     90         {
     91             char op[2];
     92             scanf("%s", op);
     93             if(op[0]=='D')
     94             {
     95                 scanf("%d", &a);
     96                 X[d++]=a;
     97                 update(a, 0, 1, n, 1);
     98             }
     99             else if(op[0]=='Q')
    100             {
    101                 scanf("%d", &a);
    102                 printf("%d
    ", query(a, 1, n, 1));
    103             }
    104             else
    105             {
    106                 if(d)
    107                 {
    108                     a=X[--d];
    109                     update(a, 1, 1, n, 1);
    110                 }
    111             }
    112         }
    113     }
    114     return 0;
    115 }
    HDOJ 1540

    扫描线类(求面积或周长)

    HDU 1542 Atlantis

    题意:给n个海报的 左上和右下 坐标, 问最后有多少露出来的面积.

     1 #define lson l, m, rt<<1
     2 #define rson m+1, r, rt<<1|1
     3 #define N 2005
     4 
     5 int cnt[N<<2];
     6 double sum[N<<2];
     7 double X[N];
     8 struct Seg
     9 {
    10     double h, l, r;
    11     int s;
    12     Seg() {}
    13     Seg(double a, double b, double c, int d) : l(a), r(b), h(c), s(d) {}
    14     bool operator < (const Seg &cmp) const
    15     {
    16         return h<cmp.h;
    17     }
    18 }ss[N];
    19 void pushup(int rt, int l, int r)
    20 {
    21     if(cnt[rt])
    22         sum[rt]=X[r+1]-X[l];
    23     else if(l==r)
    24         sum[rt]=0;
    25     else
    26         sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    27 }
    28 void update(int L, int R, int c, int l, int r, int rt)
    29 {
    30     if(L<=l && r<=R)
    31     {
    32         cnt[rt]+=c;
    33         pushup(rt, l, r);
    34         return ;
    35     }
    36     int m=(l+r)>>1;
    37     if(L<=m)
    38         update(L, R, c, lson);
    39     if(m<R)
    40         update(L, R, c, rson);
    41     pushup(rt, l, r);
    42 }
    43 
    44 int main()
    45 {
    46 #ifndef ONLINE_JUDGE
    47     freopen("in.txt", "r", stdin);
    48     freopen("out.txt", "w", stdout);
    49 #endif
    50     int n, ca=1;
    51     while(~scanf("%d", &n) && n)
    52     {
    53         int m=0;
    54         while(n--)
    55         {
    56             double a, b, c, d;
    57             scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
    58             X[m]=a;
    59             ss[m++]=Seg(a, c, b, 1);
    60             X[m]=c;
    61             ss[m++]=Seg(a, c, d, -1);
    62         }
    63         sort(X, X+m);
    64         sort(ss, ss+m);
    65         int k=1;
    66         for(int i=1;i<m;i++)
    67             if(X[i]!=X[i-1])
    68                 X[k++]=X[i];
    69         memset(cnt, 0, sizeof(cnt));
    70         memset(sum, 0, sizeof(sum));
    71         double ret=0;
    72         for(int i=0;i<m-1;i++)
    73         {
    74             int l=lower_bound(X, X+k, ss[i].l)-X;
    75             int r=lower_bound(X, X+k, ss[i].r)-X-1;
    76             if(l<=r)
    77                 update(l, r, ss[i].s, 0, k-1, 1);
    78             ret+=sum[1]*(ss[i+1].h-ss[i].h);
    79         }
    80         printf("Test case #%d
    Total explored area: %.2lf
    
    ", ca++, ret);
    81     }
    82     return 0;
    83 }
    View Code

    HDU 4419 Colorful Rectangle

    题意:有RGB三种颜色, 给出方块要涂的颜色以及左上和右下坐标, 然后依次输出颜色为R, G, B, RG, RB, GB, RGB的面积.

      1 #define lson l , m , rt << 1
      2 #define rson m + 1 , r , rt << 1 | 1
      3 const int maxn = 10005;
      4 int X[maxn<<3];
      5 
      6 struct Seg
      7 {
      8     int h , l , r, s;
      9     Seg() {}
     10     Seg(int a,int b,int c,int d) : l(a) , r(b) , h(c) , s(d) {}
     11     bool operator < (const Seg &cmp) const
     12     {
     13         return h < cmp.h;
     14     }
     15 } ss[maxn<<3];
     16 
     17 int len[maxn<<3][8],cnt[maxn<<3][8];
     18 void PushUp(int rt, int l, int r)
     19 {
     20     memset(len[rt],0, sizeof(len[rt]));
     21     int color=0;
     22     if(cnt[rt][1]>0)
     23         color+=1;
     24     if(cnt[rt][2]>0)
     25         color+=2;
     26     if(cnt[rt][4]>0)
     27         color+=4;
     28     if(cnt[rt][1] || cnt[rt][2] || cnt[rt][4])
     29     {
     30         len[rt][color]+=X[r]-X[l-1];
     31         for(int i=1; i<8; i++)
     32         {
     33             if(color!=(color|i))
     34             {
     35                 int tmp=len[rt<<1][i]+len[rt<<1|1][i];
     36                 len[rt][color|i]+=tmp;
     37                 len[rt][color]-=tmp;
     38             }
     39         }
     40     }
     41     else if(l!=r)
     42         for(int i=1; i<8; i++)
     43             len[rt][i]=len[rt<<1][i]+len[rt<<1|1][i];
     44 }
     45 
     46 void Update(int L,int R,int c, int l , int r, int rt)
     47 {
     48     if(L<=l&&r<=R)
     49     {
     50         if(c>0)
     51             cnt[rt][c]++;
     52         else
     53             cnt[rt][-c]--;
     54         //cnt[rt] += c;
     55         PushUp(rt, l, r);
     56         return ;
     57     }
     58     int m=(l+r)>>1;
     59     if(L<=m)
     60         Update(L,R,c, lson);
     61     if(m<R)
     62         Update(L,R,c, rson);
     63     PushUp(rt, l, r);
     64 }
     65 int Bin(int key,int n,int X[])
     66 {
     67     int l = 0 , r = n - 1;
     68     while(l <= r)
     69     {
     70         int m = (l + r) >> 1;
     71         if (X[m] == key) return m;
     72         if (X[m] < key) l = m + 1;
     73         else r = m - 1;
     74     }
     75     return -1;
     76 }
     77 void print(LL x)
     78 {
     79     printf(LLD, x);
     80     puts("");
     81 }
     82 int main()
     83 {
     84 #ifndef ONLINE_JUDGE
     85     freopen("in.txt", "r", stdin);
     86     freopen("out.txt", "w", stdout);
     87 #endif
     88     int t,n, ca=1;
     89     char ch;
     90     int a,b,c,d;
     91     scanf("%d",&t);
     92     while(t--)
     93     {
     94         scanf("%d",&n);
     95         int m=0;
     96         while(n--)
     97         {
     98             int e;
     99             getchar();
    100             scanf("%c%d%d%d%d",&ch,&a,&b,&c,&d);
    101             if(ch=='R')
    102                 e=1;
    103             else if(ch=='G')
    104                 e=2;
    105             else
    106                 e=4;
    107             X[m]=a;
    108             ss[m++]=Seg(a,c,b,e);
    109             X[m]=c;
    110             ss[m++]=Seg(a,c,d,-e);
    111         }
    112         sort(X,X+m);
    113         sort(ss,ss+m);
    114         int k=1;
    115         for(int i=1; i<m; i++)
    116             if(X[i]!=X[i-1])
    117                 X[k++]=X[i];
    118         LL ans[8];
    119         memset(len, 0, sizeof(len));
    120         memset(cnt, 0, sizeof(cnt));
    121         memset(ans,0, sizeof(ans));
    122         for(int i=0; i<m; i++)
    123         {
    124 //            int l=Bin(ss[i].l, k, X);
    125 //            int r=Bin(ss[i].r, k, X)-1;
    126             int l=lower_bound(X,X+k,ss[i].l)-X+1;
    127             int r=lower_bound(X,X+k,ss[i].r)-X;
    128             Update(l,r,ss[i].s, 1, k-1, 1);
    129             if(ss[i].h!=ss[i+1].h)
    130                 for(int j=1; j<8; j++)
    131                     ans[j]+=(LL)len[1][j]*(ss[i+1].h-ss[i].h);
    132         }
    133         printf("Case %d:
    ",ca++);
    134         print(ans[1]);
    135         print(ans[2]);
    136         print(ans[4]);
    137         print(ans[3]);
    138         print(ans[5]);
    139         print(ans[6]);
    140         print(ans[7]);
    141     }
    142     return 0;
    143 }
    View Code

    HDU 3255 Farming

    题意:给方土地的左上和右下坐标以及可以种的种子编号(1/2/3), 每种种子有不同收入, 输出最大收益

      1 typedef long long LL;
      2 #define lson l, m, rt<<1
      3 #define rson m+1, r, rt<<1|1
      4 #define N 1000005
      5 
      6 int X[60005];
      7 int len[N][8], cnt[N][8];
      8 struct Seg
      9 {
     10     int h, l, r, s;
     11     Seg() {}
     12     Seg(int a, int b, int c, int d) :l(a), r(b), h(c), s(d) {}
     13     bool operator < (const Seg &cmp) const
     14     {
     15         return h<cmp.h;
     16     }
     17 }ss[N<<1];
     18 
     19 void pushup(int rt, int l, int r)
     20 {
     21     memset(len[rt], 0, sizeof(len[0]));
     22     int color=0;
     23     if(cnt[rt][1]>0)
     24         color+=1;
     25     if(cnt[rt][2]>0)
     26         color+=2;
     27     if(cnt[rt][4]>0)
     28         color+=4;
     29     if(cnt[rt][1] || cnt[rt][2] || cnt[rt][4])
     30     {
     31         len[rt][color]+=X[r]-X[l-1];
     32         for(int i=1;i<8;i++)
     33             if(color!=(color|i))
     34             {
     35                 int tmp=len[rt<<1][i]+len[rt<<1|1][i];
     36                 len[rt][color|i]+=tmp;
     37                 len[rt][color]-=tmp;
     38             }
     39     }
     40     else if(l!=r)
     41         for(int i=1;i<8;i++)
     42             len[rt][i]=len[rt<<1][i]+len[rt<<1|1][i];
     43 }
     44 void update(int L, int R, int c, int l, int r, int rt)
     45 {
     46     if(L<=l && r<=R)
     47     {
     48         if(c>0)
     49             cnt[rt][c]++;
     50         else
     51             cnt[rt][-c]--;
     52         pushup(rt, l, r);
     53         return ;
     54     }
     55     int m=(l+r)>>1;
     56     if(L<=m)
     57         update(L, R, c, lson);
     58     if(m<R)
     59        update(L, R, c, rson);
     60     pushup(rt, l, r);
     61 }
     62 int Bin(int key, int n, int X[])
     63 {
     64     int l=0, r=n-1;
     65     while(l<=r)
     66     {
     67         int m=(l+r)>>1;
     68         if(X[m]==key)
     69             return m;
     70         if(X[m]<key)
     71             l=m+1;
     72         else
     73             r=m-1;
     74     }
     75     return -1;
     76 }
     77 void print(LL x)
     78 {
     79     printf(LLD, x);
     80     puts("");
     81 }
     82 int style[5];
     83 int main()
     84 {
     85     int t, ca=1;
     86     scanf("%d", &t);
     87     while(t--)
     88     {
     89         int n, M;
     90         scanf("%d%d", &n, &M);
     91         for(int i=0;i<M;i++)
     92             scanf("%d", &style[i]);
     93         int m=0;
     94         for(int i=0;i<n;i++)
     95         {
     96             int a, b, c, d, e, s;
     97             scanf("%d%d%d%d%d", &a, &b, &c, &d, &s);
     98             if(s==1)
     99                 e=1;
    100             else if(s==2)
    101                 e=2;
    102             else
    103                 e=4;
    104             X[m]=a;
    105             ss[m++]=Seg(a, c, b, e);
    106             X[m]=c;
    107             ss[m++]=Seg(a, c, d, -e);
    108         }
    109         sort(X, X+m);
    110         sort(ss, ss+m);
    111         int k=1;
    112         for(int i=1;i<m;i++)
    113             if(X[i]!=X[i-1])
    114                 X[k++]=X[i];
    115         LL ans[8];
    116         memset(ans, 0, sizeof(ans));
    117         memset(len, 0, sizeof(len));
    118         memset(cnt, 0, sizeof(cnt));
    119         for(int i=0;i<m;i++)
    120         {
    121             int l=Bin(ss[i].l, k, X)+1;
    122             int r=Bin(ss[i].r, k, X);
    123             update(l, r, ss[i].s, 1, k, 1);
    124             if(ss[i].h!=ss[i+1].h)
    125                 for(int j=1;j<8;j++)
    126                     ans[j]+=(LL)len[1][j]*(ss[i+1].h-ss[i].h);
    127         }
    128         printf("Case %d: ", ca++);
    129         if(n==1)
    130             print(ans[1]*style[0]);
    131         else if(n==2)
    132             print(ans[1]*style[0]+ans[2]*style[1]+ans[3]*max(style[0], style[1]));
    133         else
    134         {
    135             ans[1]*=style[0];
    136             ans[2]*=style[1];
    137             ans[3]*=max(style[0], style[1]);
    138             ans[4]*=style[2];
    139             ans[5]*=max(style[0], style[2]);
    140             ans[6]*=max(style[1], style[2]);
    141             ans[7]*=max(max(style[0], style[1]), style[2]);
    142             print(ans[1]+ans[2]+ans[4]+ans[3]+ans[5]+ans[6]+ans[7]);
    143         }
    144     }
    145     return 0;
    146 }
    View Code

    HDU 1828 Picture

    题意:给n个方块的左下和右上的坐标 求周长

    求周长, 除了求面积要用到的, 还要记录竖的, 合并重合的

      1 #define lson l, m, rt<<1
      2 #define rson m+1, r, rt<<1|1
      3 #define N 20005
      4 
      5 int cnt[N<<2];
      6 int sum[N<<2];
      7 int numseg[N<<2], len[N<<2];
      8 bool lbd[N<<2], rbd[N<<2];
      9 struct Seg
     10 {
     11     int h, l, r, s;
     12     Seg() {}
     13     Seg(int a, int b, int c, int d) : l(a), r(b), h(c), s(d) {}
     14     bool operator < (const Seg &cmp) const
     15     {
     16         if(h==cmp.h)
     17             return s>cmp.s;
     18         return h<cmp.h;
     19     }
     20 }ss[N];
     21 void pushup(int rt, int l, int r)
     22 {
     23     if(cnt[rt])
     24     {
     25         lbd[rt]=rbd[rt]=1;
     26         len[rt]=r-l+1;
     27         numseg[rt]=2;
     28     }
     29     else if(l==r)
     30         len[rt]=numseg[rt]=lbd[rt]=rbd[rt]=0;
     31     else
     32     {
     33         lbd[rt]=lbd[rt<<1];
     34         rbd[rt]=rbd[rt<<1|1];
     35         len[rt]=len[rt<<1]+len[rt<<1|1];
     36         numseg[rt]=numseg[rt<<1]+numseg[rt<<1|1];
     37         if(lbd[rt<<1|1] && rbd[rt<<1])
     38             numseg[rt]-=2;
     39     }
     40 }
     41 void update(int L, int R, int c, int l, int r, int rt)
     42 {
     43     if(L<=l && r<=R)
     44     {
     45         cnt[rt]+=c;
     46         pushup(rt, l, r);
     47         return ;
     48     }
     49     int m=(l+r)>>1;
     50     if(L<=m)
     51         update(L, R, c, lson);
     52     if(m<R)
     53         update(L, R, c, rson);
     54     pushup(rt, l, r);
     55 }
     56 int Bin(double key, int n, double X[])
     57 {
     58     int l=0, r=n-1;
     59     while(l<=r)
     60     {
     61         int m=(l+r)>>1;
     62         if(X[m]==key)
     63             return m;
     64         if(X[m]<key)
     65             l=m+1;
     66         else
     67             r=m-1;
     68     }
     69     return -1;
     70 }
     71 int main()
     72 {
     73 #ifndef ONLINE_JUDGE
     74     freopen("in.txt", "r", stdin);
     75     freopen("out.txt", "w", stdout);
     76 #endif
     77     int n;
     78     while(~scanf("%d", &n))
     79     {
     80         int m=0;
     81         int minn=INT_MAX, maxn=-INT_MAX;
     82         while(n--)
     83         {
     84             int a, b, c, d;
     85             scanf("%d%d%d%d", &a, &b, &c, &d);
     86             minn=min(minn, a);
     87             maxn=max(maxn, c);
     88             ss[m++]=Seg(a, c, b, 1);
     89             ss[m++]=Seg(a, c, d, -1);
     90         }
     91         sort(ss, ss+m);
     92         int ret=0, last=0;
     93         for(int i=0;i<m;i++)
     94         {
     95             if(ss[i].l<ss[i].r)
     96                 update(ss[i].l, ss[i].r-1, ss[i].s, minn, maxn-1, 1);
     97             ret+=numseg[1]*(ss[i+1].h-ss[i].h);
     98             ret+=abs(len[1]-last);
     99             last=len[1];
    100         }
    101         printf("%d
    ", ret);
    102     }
    103     return 0;
    104 }
    View Code
  • 相关阅读:
    Git 切换本地分支 切换远程分支
    ThreeJs 模型的缩放、移动、旋转 以及使用鼠标对三维物体的缩放
    ThreeJs 绘制点、线、面
    阿里云短信验证使用(PHP)
    Swoft 容器使用
    Swoft 缓存及Redis使用
    Swoft 图片上传与处理
    使用 webpack 搭建多入口项目
    使用 nodeJs 开发微信公众号(上传图片)
    使用 nodeJs 开发微信公众号(设置自动回复消息)
  • 原文地址:https://www.cnblogs.com/Empress/p/4000877.html
Copyright © 2011-2022 走看看