bzoj2011: [Ceoi2010]Mp3 Player
Description
Georg有个MP3 Player,没有任何操作T秒钟就会锁定,这时按下任意一个键就会变回没锁定的状态,但不会改变频道。只有在没锁定的状态下按键才有可能改变频道。 MP3的频道为0~Vmax(2<=Vmax<=5000),如果现在是X频道,若X<>Vmax,在无锁状态下按+,X就会加1。若X<>0,在无锁状态下按-,X就会减一。 想在Georg忘记了MP3的T是多少。他想通过一段操作试验一下。然后他就写下他的操作顺序和最后停留的频道V2(0<=V2<=Vmax),然后就给你了,你要求的是T的最大值和T在这个值的情况下,第一个操作前的频道V1的最大可能数。若T为无限大时经过这段操作最后能停在V2,则输出infinity。
Input
第1行:N,Vmax,V2 N表示Georg操作了N次(2<=N<=100000); 以下N行,每行第一个为字符C(C为'+'或'-'),第二个为数字Ti(0<=Ti<=10^9), 表示Georg在Ti秒按下了C键。
Output
如题所述。
Sample Input
6 4 3
- 0
+ 8
+ 9
+ 13
- 19
- 24
- 0
+ 8
+ 9
+ 13
- 19
- 24
Sample Output
5 4
题解:
这题肯定要从大到小枚举T,判断这时有效的操作能否有解
判断能否有解有两种做法
第一种是将所有操作倒过来作,这样加边减,减变加
无解的情况就是 在未到达过0之前,最后某段音量>vmax 或未到达过vmax之前,最后某段音量<0
然后就是分情况讨论了
如果没有到过vmax,那么最大初始音量为所有操作之和
否则就是vmax
第二种就是类似清华集训V那题一样的去维护一个分段函数f(x)
其定义域为[0,vmax],表示这段操作的初始音量,值域也为[0,vmax],表示这段操作后的音量为多少
然后也是一通讨论
code:
第一种:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 char ch; 8 bool ok; 9 void read(int &x){ 10 ok=0; 11 for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 12 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 13 if (ok) x=-x; 14 } 15 const int maxn=100005; 16 const int inf=0x7f7f7f7f; 17 char s[2]; 18 int n,vm,v[maxn]; 19 struct oper{ 20 int id,t; 21 }op[maxn]; 22 bool cmp(const oper &a,const oper &b){return a.t>b.t;} 23 void write(int a,int b){ 24 if (a==inf) puts("infinity"); 25 else printf("%d %d\n",a,b); 26 } 27 struct Node{ 28 int sum,maxv,minv; 29 }; 30 Node operator+(const Node &a,const Node &b){return (Node){a.sum+b.sum,max(a.maxv,a.sum+b.maxv),min(a.minv,a.sum+b.minv)};} 31 struct Seg{ 32 Node node[maxn<<2],res,tmp; 33 void build(int k,int l,int r){ 34 if (l==r){node[k]=(Node){v[l],v[l],v[l]};return;} 35 int m=(l+r)>>1; 36 build(k<<1,l,m),build((k<<1)+1,m+1,r),node[k]=node[k<<1]+node[(k<<1)+1]; 37 } 38 void modify(int k,int l,int r,int x){ 39 if (l==r){node[k]=(Node){0,0,inf};return;} 40 int m=(l+r)>>1; 41 if (x<=m) modify(k<<1,l,m,x); else modify((k<<1)+1,m+1,r,x); 42 node[k]=node[k<<1]+node[(k<<1)+1]; 43 } 44 int query_max(int k,int l,int r){ 45 if (l==r){tmp=res+node[k];return tmp.maxv<vm;} 46 int m=(l+r)>>1; 47 tmp=res+node[k<<1]; 48 if (tmp.maxv>=vm) return query_max(k<<1,l,m); 49 res=tmp; return query_max((k<<1)+1,m+1,r)+(m-l+1); 50 } 51 int query_min(int k,int l,int r){ 52 if (l==r){tmp=res+node[k];return tmp.minv>0;} 53 int m=(l+r)>>1; 54 tmp=res+node[k<<1]; 55 if (tmp.minv<=0) return query_min(k<<1,l,m); 56 res=tmp; return query_min((k<<1)+1,m+1,r)+(m-l+1); 57 } 58 Node query(int k,int l,int r,int x){ 59 if (l==r) return node[k]; 60 int m=(l+r)>>1; 61 if (x<=m) return query(k<<1,l,m,x); 62 else return node[k<<1]+query((k<<1)+1,m+1,r,x); 63 } 64 bool check(int ans){ 65 int t1,t2; 66 res=(Node){0,0,inf},t1=query_max(1,0,n-1); 67 res=(Node){0,0,inf},t2=query_min(1,0,n-1); 68 if (t1==n&&t2==n){write(ans,node[1].sum);return true;} 69 if (t1>t2){ 70 res=query(1,0,n-1,t1); 71 if (res.minv<0) return false; 72 if (t1==n) write(ans,node[1].sum); 73 else write(ans,vm); 74 return true; 75 } 76 else{ 77 res=query(1,0,n-1,t2); 78 if (res.maxv>vm) return false; 79 write(ans,vm); 80 return true; 81 } 82 return false; 83 } 84 }T; 85 int main(){ 86 read(n),read(vm),read(v[0]); 87 for (int i=n;i>=1;i--) scanf("%s",s),v[i]=s[0]=='+'?-1:1,read(op[i].t),op[i].id=i; 88 T.build(1,0,n-1); 89 if (T.check(inf)) return 0; 90 for (int i=1;i<n;i++) op[i].t-=op[i+1].t; 91 sort(op+1,op+n,cmp); 92 for (int i=1,j;i<n;i=j){ 93 for (j=i;op[j].t==op[i].t;j++) T.modify(1,0,n-1,op[j].id); 94 if (T.check(op[i].t-1)) return 0; 95 } 96 return 0; 97 }
第二种:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 char ch; 8 bool ok; 9 void read(int &x){ 10 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 11 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 12 if (ok) x=-x; 13 } 14 const int maxn=100005; 15 inline int min(const int &a,const int &b){ 16 int diff=b-a; 17 return a+(diff&(diff>>31)); 18 } 19 inline int max(const int &a,const int &b){ 20 int diff=b-a; 21 return b-(diff&(diff>>31)); 22 } 23 char s[2]; 24 int n,vm,v2; 25 struct Oper{ 26 int op,t,id; 27 }oper[maxn]; 28 bool cmp(const Oper &a,const Oper &b){return a.t>b.t||(a.t==b.t&&a.id<b.id);} 29 struct Data{ 30 int a,b,c; 31 void init(){a=0,b=vm,c=0;} 32 }res; 33 Data operator+(const Data &x,const Data &y){return (Data){min(y.b,max(y.a,x.a+y.c)),max(y.a,min(y.b,x.b+y.c)),x.c+y.c};} 34 struct Seg{ 35 #define ls k<<1 36 #define rs (k<<1)+1 37 Data val[maxn<<2]; 38 void build(int k,int l,int r){ 39 if (l==r){val[k]=(Data){0,vm,oper[l].op};return;} 40 int m=(l+r)>>1; 41 build(ls,l,m),build(rs,m+1,r),val[k]=val[ls]+val[rs]; 42 } 43 void modify(int k,int l,int r,int x){ 44 if (l==r){val[k].init();return;} 45 int m=(l+r)>>1; 46 if (x<=m) modify(ls,l,m,x); else modify(rs,m+1,r,x); 47 val[k]=val[ls]+val[rs]; 48 } 49 void modify(int x,int op){modify(1,2,n,x);} 50 }T; 51 int calc(){ 52 if (v2==res.b&&res.b-res.c<=vm) return vm; 53 return max(0,min(v2-res.c,vm)); 54 } 55 int f(int x){return min(res.b,max(res.a,x+res.c));} 56 int main(){ 57 read(n),read(vm),read(v2); 58 for (int i=1;i<=n;i++) scanf("%s",s),read(oper[i].t),oper[i].op=s[0]=='+'?1:-1,oper[i].id=i; 59 T.build(1,2,n); 60 for (int i=n;i>=1;i--) oper[i].t-=oper[i-1].t; 61 sort(oper+2,oper+n+1,cmp); 62 res=T.val[1]; 63 if (f(0)<=v2&&v2<=f(vm)){puts("infinity");return 0;} 64 for (int i=2,j;i<=n;i=j){ 65 for (j=i;oper[j].t==oper[i].t;j++) T.modify(oper[j].id,oper[j].op); 66 res=T.val[1]; 67 if (f(0)<=v2&&v2<=f(vm)){printf("%d %d\n",oper[i].t-1,calc());return 0;} 68 } 69 return 0; 70 }