首页 > 代码库 > HDU 4973 A simple simulation problem.(线段树)
HDU 4973 A simple simulation problem.(线段树)
http://acm.hdu.edu.cn/showproblem.php?pid=4973
A simple simulation problem.Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 451 Accepted Submission(s): 175
Problem Description
There are n types of cells in the lab, numbered from 1 to n. These cells are put in a queue, the i-th cell belongs to type i. Each time I can use mitogen to double the cells in the interval [l, r]. For instance, the original queue is {1 2 3 3 4 5}, after using a mitogen in the interval [2, 5] the queue will be {1 2 2 3 3 3 3 4 4 5}. After some operations this queue could become very long, and I can’t figure out maximum count of cells of same type. Could you help me?
Input
The first line contains a single integer t (1 <= t <= 20), the number of test cases.
For each case, the first line contains 2 integers (1 <= n,m<= 50000) indicating the number of cell types and the number of operations.
For the following m lines, each line represents an operation. There are only two kinds of operations: Q and D. And the format is:
“Q l r”, query the maximum number of cells of same type in the interval [l, r];
“D l r”, double the cells in the interval [l, r];
(0 <= r – l <= 10^8, 1 <= l, r <= the number of all the cells)
For each case, the first line contains 2 integers (1 <= n,m<= 50000) indicating the number of cell types and the number of operations.
For the following m lines, each line represents an operation. There are only two kinds of operations: Q and D. And the format is:
“Q l r”, query the maximum number of cells of same type in the interval [l, r];
“D l r”, double the cells in the interval [l, r];
(0 <= r – l <= 10^8, 1 <= l, r <= the number of all the cells)
Output
For each case, output the case number as shown. Then for each query "Q l r", print the maximum number of cells of same type in the interval [l, r].
Take the sample output for more details.
Take the sample output for more details.
Sample Input
1 5 5 D 5 5 Q 5 6 D 2 3 D 1 2 Q 1 7
Sample Output
Case #1: 2 3
Source
2014 Multi-University Training Contest 10
题意:
初始给出1-n的序列,有两个操作:
D l r,将[l,r]区间的每个数都复制一个;
Q l r,询问[l,r]区间内最多的相同数字的个数。
分析:
显然的线段树,但是这个序列的长度会因为D操作变化,即线段长度变化。通过观察发现这个序列永远是sort过的,那么我们只要维护每个数的数量,操作前找到l和r的位置,然后再单点更新、成段更新,成段询问,线段树的综合应用。
/* * * Author : fcbruce * * Date : 2014-08-24 09:53:20 * */ #include <cstdio> #include <iostream> #include <sstream> #include <cstdlib> #include <algorithm> #include <ctime> #include <cctype> #include <cmath> #include <string> #include <cstring> #include <stack> #include <queue> #include <list> #include <vector> #include <map> #include <set> #define sqr(x) ((x)*(x)) #define LL long long #define itn int #define INF 0x3f3f3f3f #define PI 3.1415926535897932384626 #define eps 1e-10 #ifdef _WIN32 #define lld "%I64d" #else #define lld "%lld" #endif #define maxm #define maxn 50007 using namespace std; long long sum[maxn<<2],mul[maxn<<2],maxv[maxn<<2]; inline void pushdown(int k) { if (mul[k]) { int lc=k*2+1,rc=k*2+2; mul[lc]+=mul[k];mul[rc]+=mul[k]; sum[lc]<<=mul[k];sum[rc]<<=mul[k]; maxv[lc]<<=mul[k];maxv[rc]<<=mul[k]; mul[k]=0; } } inline void pushup(int k) { int lc=k*2+1,rc=k*2+2; sum[k]=sum[lc]+sum[rc]; maxv[k]=max(maxv[lc],maxv[rc]); } void build(int k,int l,int r) { mul[k]=0; if (r-l==1) { sum[k]=1; maxv[k]=1; return ; } build(k*2+1,l,l+r>>1); build(k*2+2,l+r>>1,r); pushup(k); } void update_plus(int p,LL v,int k,int l,int r) { if (r-l==1) { sum[k]+=v; maxv[k]+=v; return ; } pushdown(k); int m=l+r>>1; if (p<m) update_plus(p,v,k*2+1,l,m); else update_plus(p,v,k*2+2,m,r); pushup(k); } void update_mul(int a,int b,int k,int l,int r) { if (b<=l || r<=a) return ; if (a<=l && r<=b) { sum[k]<<=1; mul[k]++; maxv[k]<<=1; return ; } pushdown(k); update_mul(a,b,k*2+1,l,l+r>>1); update_mul(a,b,k*2+2,l+r>>1,r); pushup(k); } int query_pos(LL s,int k,int l,int r) { if (r-l==1) return l; int lc=k*2+1,rc=k*2+2; pushdown(k); if (s<=sum[lc]) return query_pos(s,lc,l,l+r>>1); else return query_pos(s-sum[lc],rc,l+r>>1,r); } LL query_sum(int a,int b,int k,int l,int r) { if (b<=l || r<=a) return 0; if (a<=l && r<=b) { return sum[k]; } pushdown(k); return query_sum(a,b,k*2+1,l,l+r>>1)+query_sum(a,b,k*2+2,l+r>>1,r); } LL query_max(int a,int b,int k,int l,int r) { if (b<=l || r<=a) return 0; if (a<=l && r<=b) { return maxv[k]; } pushdown(k); return max(query_max(a,b,k*2+1,l,l+r>>1),query_max(a,b,k*2+2,l+r>>1,r)); } int main() { #ifndef ONLINE_JUDGE freopen("/home/fcbruce/文档/code/t","r",stdin); #endif // ONLINE_JUDGE int T_T,__=0; scanf( "%d",&T_T); while (T_T--) { printf( "Case #%d:\n",++__); int n,m; scanf( "%d%d",&n,&m); build(0,0,n); long long l,r; char op; for (int i=0;i<m;i++) { scanf( " %c" lld lld ,&op,&l,&r); int a=query_pos(l,0,0,n); int b=query_pos(r,0,0,n); if (op=='D') { if (a==b) { update_plus(a,r-l+1,0,0,n); } else { LL v1=query_sum(0,a+1,0,0,n)-l+1; LL v2=r-query_sum(0,b,0,0,n); update_plus(a,v1,0,0,n); update_plus(b,v2,0,0,n); if (a+1<b) update_mul(a+1,b,0,0,n); } } else { LL MAX=0; if (a==b) { MAX=r-l+1; } else { MAX=query_sum(0,a+1,0,0,n)-l+1; MAX=max(MAX,r-query_sum(0,b,0,0,n)); if (a+1<b) MAX=max(MAX,query_max(a+1,b,0,0,n)); } printf ( lld "\n",MAX); } } } return 0; }
HDU 4973 A simple simulation problem.(线段树)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。