HDU 3577 Fast Arrangement (线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3577

题意不好理解,给你数字k表示这里车最多同时坐k个人,然后有q个询问,每个询问是每个人的上车和下车时间,每个人按次序上车,问哪些人能上车输出他们的序号。

这题用线段树的成段更新,把每个人的上下车时间看做一个线段,每次上车就把这个区间都加1,但是上车的前提是这个区间上的最大值不超过k。有个坑点就是一个人上下车的时间是左闭右开区间,可以想到要是一个人下车,另一个人上车,这个情况下这个点的大小还是不变的。还有注意格式...

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 using namespace std;
  5 const int MAXN = 1e6 + 5;
  6 struct segtree {
  7     int l , r , sum , add;
  8 }T[MAXN << 2];
  9 int x[MAXN / 10] , y[MAXN / 10] , ans[MAXN / 10];
 10
 11 void init(int p , int l , int r) {
 12     int mid = (l + r) >> 1;
 13     T[p].l = l , T[p].r = r , T[p].add = 0;
 14     if(l == r) {
 15         T[p].sum = 0;
 16         return ;
 17     }
 18     init(p << 1 , l , mid);
 19     init((p << 1)|1 , mid + 1 , r);
 20     T[p].sum = max(T[p << 1].sum , T[(p << 1)|1].sum);
 21 }
 22
 23 void updata(int p , int l , int r , int val) {
 24     int mid = (T[p].l + T[p].r) >> 1;
 25     if(l == T[p].l && T[p].r == r) {
 26         T[p].sum += val;
 27         T[p].add += val;
 28         return ;
 29     }
 30     if(T[p].add) {
 31         T[p << 1].sum += T[p].add;
 32         T[p << 1].add += T[p].add;
 33         T[(p << 1)|1].sum += T[p].add;
 34         T[(p << 1)|1].add += T[p].add;
 35         T[p].add = 0;
 36     }
 37     if(r <= mid) {
 38         updata(p << 1 , l , r , val);
 39     }
 40     else if(l > mid) {
 41         updata((p << 1)|1 , l , r , val);
 42     }
 43     else {
 44         updata(p << 1 , l , mid ,val);
 45         updata((p << 1)|1 , mid + 1 , r , val);
 46     }
 47     T[p].sum = max(T[p << 1].sum , max(T[(p << 1)|1].sum , T[p].sum));
 48 }
 49
 50 int query(int p , int l , int r) {
 51     int mid = (T[p].l + T[p].r) >> 1;
 52     if(l == T[p].l && T[p].r == r) {
 53         return T[p].sum;
 54     }
 55     if(T[p].add) {
 56         T[p << 1].sum += T[p].add;
 57         T[p << 1].add += T[p].add;
 58         T[(p << 1)|1].sum += T[p].add;
 59         T[(p << 1)|1].add += T[p].add;
 60         T[p].add = 0;
 61     }
 62     if(r <= mid) {
 63         return query(p << 1 , l , r);
 64     }
 65     else if(l > mid) {
 66         return query((p << 1)|1 , l , r);
 67     }
 68     else {
 69         return max(query(p << 1 , l , mid) , query((p << 1)|1 , mid + 1 , r));
 70     }
 71 }
 72
 73 int main()
 74 {
 75     int t , k , m;
 76     scanf("%d" , &t);
 77     for(int ca = 1 ; ca <= t ; ca++) {
 78         scanf("%d %d" , &k , &m);
 79         int len = -1;
 80         for(int i = 1 ; i <= m ; i++) {
 81             scanf("%d %d" , x + i , y + i);
 82             y[i]--;
 83             len = max(x[i] , len);
 84             len = max(y[i] , len);
 85         }
 86         init(1 , 1 , len);
 87         int cont = 0;
 88         for(int i = 1 ; i <= m ; i++) {
 89             int temp = query(1 , x[i] , y[i]);
 90             if(temp < k) {
 91                 ans[++cont] = i;
 92                 updata(1 , x[i] , y[i] , 1);
 93             }
 94         }
 95         printf("Case %d:\n" , ca);
 96         for(int i = 1 ; i <= cont ; i++) {
 97             printf("%d " , ans[i]);
 98         }
 99         printf("\n\n");
100     }
101 }
时间: 2024-11-09 13:24:08

HDU 3577 Fast Arrangement (线段树区间更新)的相关文章

HDU 4902 Nice boat --线段树(区间更新)

题意:给一个数字序列,第一类操作是将[l,r]内的数全赋为x ,第二类操作是将[l,r]中大于x的数赋为该数与x的gcd,若干操作后输出整个序列. 解法: 本题线段树要维护的最重要的东西就是一个区间内所有数是否相等的标记.只维护这个东西都可以做出来. 我当时想歪了,想到维护Max[rt]表示该段的最大值,最大值如果<=x的话就不用更新了,但是好像加了这个“优化”跑的更慢了. 我想大概是因为如果两个子树最大值或者整个两个子树的数不完全相等的话,根本不能直接下传这个值或者下传gcd,因为你不知道要更

hdu 1698+poj 3468 (线段树 区间更新)

http://acm.hdu.edu.cn/showproblem.php?pid=1698 这个题意翻译起来有点猥琐啊,还是和谐一点吧 和涂颜色差不多,区间初始都为1,然后操作都是将x到y改为z,注意 是改为z,不是加或减,最后输出区间总值 也是线段树加lazy操作 1 #include<cstdio> 2 using namespace std; 3 struct point { 4 int l,r; 5 int val,sum; 6 }; 7 point tree[400007]; 8

hdu 3397 Sequence operation 线段树 区间更新 区间合并

题意: 5种操作,所有数字都为0或1 0 a b:将[a,b]置0 1 a b:将[a,b]置1 2 a b:[a,b]中的0和1互换 3 a b:查询[a,b]中的1的数量 4 a b:查询[a,b]中的最长连续1串的长度 这题看题目就很裸,综合了区间更新,区间合并 我一开始把更新操作全放一个变量,但是在push_down的时候很麻烦,情况很多,容易漏,后来改成下面的 更新的操作可以分为两类,一个是置值(stv),一个是互换(swp).如果stv!=-1,则更新儿子节点的stv,并将儿子的sw

Hdu 3966 Aragorn&#39;s Story (树链剖分 + 线段树区间更新)

题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x: 3:(Q, x) 查询节点x的权值为多少? 解题思路: 可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新 1 #include <cstdio> 2 #include

HDU 5023 A Corrupt Mayor&#39;s Performance Art 线段树区间更新+状态压缩

Link:  http://acm.hdu.edu.cn/showproblem.php?pid=5023 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <string> 7 #include <cmath> 8 using namesp

HDU 5023 A Corrupt Mayor&#39;s Performance Art(线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色,有两种操作: P a b c  把区间a到b涂成c颜色 Q a b 查询区间a到b的颜色 线段树区间更新,每个节点保存的信息有,存储颜色的c,30种颜色可以压缩到一个int型里面存储,然后还有一个tot,表示这个区间一共有多少种颜色. 对于P操作,依次往下寻找,找要更新的区间,找到要更新的区间之前

HDU 4902 Nice boat(线段树 区间更新)

Nice boat 大意:给你一个区间,每次可以进行两种操作,1:把区间中的数全都变成x  2:把区间中大于x的数变成gcd(a[i], x),最后输出序列. 思路:线段树成段更行,用num数组的叶子存储数据,节点当作lazy来使用. 1 #include <stdio.h> 2 const int maxn = 100005; 3 4 int num[maxn<<2]; 5 6 int gcd(int a, int b){ 7 return b?gcd(b, a%b):a; 8

HDU 1698 Just a Hook (线段树,区间更新)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 17214    Accepted Submission(s): 8600 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f

HDU 1698 Just a Hook (线段树 区间更新基础)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 21856    Accepted Submission(s): 10963 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible thing