hdu 4266 The Worm in the Apple (线段树)
2015-07-24 20:52
295 查看
/* 题意:给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每个花瓶最多插一朵花。 然后有2个操作。 操作1,a b c ,往在a位置后面(包括a)插b朵花,输出插入的首位置和末位置。 操作2,a b ,输出区间[a , b ]范围内的花的数量,然后全部清空。 很显然这是一道线段树。区间更新,区间求和,这些基本的操作线段树都可以logN的时间范围内完成。 操作2,很显然就是线段树的区间求和,求出[a , b]范围内的花朵的数量,区间更新,将整个区间全部变成0。 操作1,这里我们首先需要找出他的首位置和末位置,所以需要二分他的位置。 首先我们二分他的首位置, l = a , r = n ,在这个区间内二分,找出第一个0的位置,那就是该操作的首位置pos1。 然后再二分他的末位置,l = pos1 , r = n ,找到第b个0,就是该操作的末位置pos2,然后区间更新[pos1 ,pos2]全部置为1。 */ #include <cstdio> # include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 ///lson和rson分别表示结点的左儿子和右儿子 ///rt表示当前子树的根(root),也就是当前所在的结点 const int maxn =60010; ///maxn是题目给的最大区间,而节点数要开4倍,确切的来说节点数要开大于maxn的最小2x的两倍 int sum[maxn<<2];///求和 int col[maxn<<2];///用来标记每个节点,为0则表示没有标记,否则为标记 int str[maxn]; void PushUP(int rt)///PushUP(int rt)是把当前结点的信息更新到父结点 { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void PushDown(int rt,int m)///pushDown(int rt)是把当前结点的信息更新给儿子结点,m为分区间的长度 { if (col[rt])///被标记过,说明区间改变了 { col[rt<<1] = col[rt<<1|1] = 1; sum[rt<<1] = (m - (m >> 1)) * col[rt];///更新左儿子的和 sum[rt<<1|1] = (m >> 1) * col[rt];///更新右儿子的和 col[rt] = -1;///将标记向儿子节点移动后,父节点的延迟标记去掉 ///传递后,当前节点标记域清空 } else { col[rt<<1] = col[rt<<1|1] = 0; sum[rt<<1] = sum[rt<<1|1] = 0; col[rt] = -1; } } void build(int l,int r,int rt)///建树 { col[rt] = -1; if (l == r) { sum[rt]=0; // scanf("%lld",&sum[rt]); return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUP(rt); } void update(int L,int R,int c,int l,int r,int rt) { if(L <= l && r <= R) { col[rt]= c; sum[rt]= c *(r - l +1); return; } if(col[rt]!=-1) PushDown(rt , r - l +1); int m =(l + r)>>1; if(L <= m) update(L , R , c , lson); if(R > m) update(L , R , c , rson); PushUP(rt); } int query(int L,int R,int l,int r,int rt)///区间求和 { if (L <= l && r <= R) { return sum[rt]; } if(col[rt]!=-1) PushDown(rt , r - l + 1);///要取rt子节点的值时,也要先把rt的延迟标记向下移动 int m = (l + r) >> 1; int ret = 0; if (L <= m) ret += query(L , R , lson); if (m < R) ret += query(L , R , rson); return ret; } int main() { int t,m,n,a,b,c; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); build(1,n,1); while(m--) { scanf("%d",&a); if(a==1) { scanf("%d%d",&b,&c); b++; c=min(c,(n-b+1)-query(b,n,1,n,1)); if(c==0) { printf("Can not put any one.\n"); continue; } int left=b; int right=n; while(left<=right) { int mid=(left+right)/2; if(query(b,mid,1,n,1)<mid-b+1) right=mid-1; else left=mid+1; } b=left; right=n; while(left<=right) { int mid=(left+right)/2; int ans1=query(b,mid,1,n,1); int ans2=mid-b+1; int ans=ans2-ans1; if(ans<c) left=mid+1; else right=mid-1; } if(left>n) left=n; printf("%d %d\n",b-1,left-1); update(b,left,1,1,n,1); } else { scanf("%d%d",&b,&c); b++; c++; if(b>=n) b=n; if(c>=n) c=n; int ans=query(b,c,1,n,1); printf("%d\n",ans); update(b,c,0,1,n,1); // printf("%d\n",query(b,c,1,n,1)); } } printf("\n"); } return 0; } /* 10 10 4 1 2 9 1 0 9 2 0 9 2 0 1 10 5 1 3 5 2 4 5 1 1 8 2 3 6 1 8 8 10 6 1 2 5 2 3 4 1 0 8 2 2 5 1 4 4 1 2 3 */
相关文章推荐
- ADO.NET TableMappings使用方法
- 【iOS开发之Objective-C】单例的创建
- 【转】Android世界的Swift - Kotlin语言
- Swift 中使用 SwiftyJSON 制作一个比特币价格 APP
- Android之自定义checkbox样式
- Android:TabHost实现Tab切换
- [cocos2dx]抽象元素——CCCamera摄像机类
- 史上最强劲的android模拟器命令详解
- iOS 学习资料整理
- Android-Service
- iOS获取文件夹中存储空间的大小、手机剩余空间大小、手机总空间大小 工具
- iOS单元测试编码规范
- iOS如何测试单例?
- 在win7在结构cocos2d-x v3.2rc0开发环境(For Android)
- iOS 什么时候用 copy、weak、strong、assign?
- iOS单元测试编码规范
- IOS开发笔记之二十九——一个野指针引起的bug
- android--活用强大的自定义drawable功能
- Objective-C学习笔记(二十五)——属性与方法的继承学习
- Android中图片的放大。