2015湖南省队集训DAY4——hoodle
来源:互联网 发布:网络经常被攻击 编辑:程序博客网 时间:2024/05/16 11:46
弹珠 (hoodle)
【问题描述】
D.Ash 是一个喜欢玩弹珠的小男孩,他有一盒五颜六色的弹珠,在阳光的照射下非
美丽。
同样,他喜欢聆听弹珠相碰时的清脆声音。
经过他的观察,每个弹珠有三个参数 , , ,均为正整数,
分别为弹珠的碰撞损耗,发射损耗和发射能量,
用弹珠 x 撞击弹珠 y ,发出的声音响度为 B_{x,y}=max{- * + ,0}。
Ash 会把弹珠从弹珠盒中拿出来插入到现有弹珠序列中,戒替换现有弹珠序列中已
的弹珠,
Ash 会先告诉你操作的类型, “Insert” 表示插入, “Change” 表示替换。
Ash 的每个操作有两个参数 t, 。
若操作类型为 “Insert”,表示把碰撞损耗为 的弹珠插入到当前序列第 t 个弹珠之
后,t=0 表示将该弹珠插入到当前序列的第一个。
若操作类型为 “Change”,表示把当前序列第 t 个弹珠之后的弹珠修改为碰撞损耗为
的弹珠,t=0 表示修改当前序列的第一个弹珠。
Ash 要玩这么一个游戏:
他先把第一颗弹珠放入袋中,然后从袋子中取出一颗弹珠撞击第二颗弹珠,
然后把第二颗弹珠收入袋中,然后从袋子中取出一颗弹珠撞击第三颗弹珠,
然后把第三颗弹珠收入袋中,然后从袋子中取出一颗弹珠撞击第四颗弹珠,
以此类推………
对亍第 i 颗弹珠 (i!=1),可以使用前 i-1 颗弹珠中的任何一颗来撞击它 ,并且每颗
珠可以使用多次。
Ash 告诉你,经过他的摆放,保证当前序列中 , 是单调上升的。
他希望你能告诉他,对亍第 2~n 颗弹珠中的每颗弹珠的最大撞击响度是多少。
【输入格式】
第 1 行,两个数,n,m。
第 2~m+1 行,每行一个字符串和两个数,表示操作。
第 m+2~m+1+n 行,每行两个数,分别为 和 。
【输出格式】
输出 n-1 行,每行一个数,第 i 行表示第 i+1 弹珠的最大撞击响度。
【样例输入】
5 10
Insert 0 10
Change 0 2
Insert 0 2
Change 0 10
Insert 2 4
Insert 1 8
Change 1 2
Change 0 5
Insert 1 2
Change 1 4
1 5
2 10
3 14
4 17
5 19
【样例输出】
1
6
8
2
【样例解释】
第1 次操作后,序列为{10}
第2 次操作后,序列为{2}
第3 次操作后,序列为{2,2}
第4 次操作后,序列为{10,2}
第5 次操作后,序列为{10,2,4}
第6 次操作后,序列为{10,8,2,4}
第7 次操作后,序列为{10,2,2,4}
第8 次操作后,序列为{5,2,2,4}
第9 次操作后,序列为{5,2,2,2,4}
第10 次操作后,序列为{5,4,2,2,4}
对亍第2颗弹珠,B_{1,2}=1, 最大值为 1
对亍第3颗弹珠,B_{1,3}=3,B_{2,3}=6,最大值为 6
对亍第4颗弹珠,B_{1,4}=3,B_{2,4}=6,B_{3,4}=8,最大值为8
对亍第5颗弹珠,B_{1,5}=1,B_{2,5}=2,B_{3,5}=2,B_{4,5}=1,最大值为 2
【数据范围】
对亍前 30% 的数捤, n <= 1000, m <= 3000
对亍前 50% 的数捤, n <= 10000,m <= 20000
对亍 100% 的数捤, n <= 400000,m <= 500000,0< , , <= 10^9
数捤是有梯度的。
题解+吐槽:
是在去年湖南集训时听说splay这东西的,那时年轻,啥都不懂,没想到现在这种东西已经是sb玩意了。
是在更早的时候听说斜率优化这东西的,那时年轻,啥都不懂,没想到现在连我都能写出来了。
这题是俩基础题拼起来的。
第一个任务是维护序列。
因为没有强制在线,所以可以倒序处理,用线段树/树状数组维护。
然而我傻逼只会splay。
第二个任务是求一个看上去就是斜率优化的东西。
还顺便送了个点的坐标递增的条件。
于是直接上单调栈,维护上凸壳。
然后每次询问时在上凸壳上二分查找满足条件的点。
再就是一些细节问题,稍不注意就会写挂。。。
(P.S.这题的数据生成器真是淡腾)
代码在这:
(因为是考场代码,所以会有些奇怪的注释,而且为了方便(我懒癌晚期),我把splay在暴力部分里粘了一份,然后就6k了。。。另外还有快速输出)
#include <cstdio>const int inf=0x3f3f3f3f;using namespace std;typedef long long ll;typedef double db;int getint(){ int f=1,g=0; char c=getchar(); while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0' && c<='9')g=(g<<3)+(g<<1)+c-'0',c=getchar(); return f*g;}int n,m;template<class T>T max(const T& a,const T& b){ return a>b? a:b;}namespace brute_force{ #define lc ch[x][0] #define rc ch[x][1] #define key_value ch[ch[root][1]][0] const int maxn=900005; int pre[maxn]; int ch[maxn][2]; int val[maxn]; int size[maxn]; int root; int tot; int all; int a[maxn]; int p[maxn]; int q[maxn]; int newnode(int v,int fa) { int x=++tot; lc=rc=0; pre[x]=fa; val[x]=v; size[x]=1; return x; } void up(int x) { size[x]=size[lc]+size[rc]+1; } void rotate(int x) { int y=pre[x]; int f=(ch[y][0]==x); pre[x]=pre[y]; pre[ch[x][f]]=y; ch[y][!f]=ch[x][f]; if(pre[y]) { ch[pre[y]][ch[pre[y]][1]==y]=x; } pre[y]=x; ch[x][f]=y; up(y); up(x); } void splay(int x,int goal) { while(pre[x]!=goal) { int y=pre[x],z=pre[y]; if(pre[y]!=goal){ if((ch[z][0]==y)^(ch[y][0]==x))rotate(x); else rotate(y); } rotate(x); } up(x); if(goal==0)root=x; } int findk(int x,int k){ if(!x)return 0; if(k<=size[lc])return findk(lc,k); if(k>size[lc]+1)return findk(rc,k-size[lc]-1); return x; } void split(int l,int r) { splay(findk(root,l),0); splay(findk(root,r+2),root); } void insert(int p,int v) { split(p,p-1); key_value=newnode(v,ch[root][1]); up(ch[root][1]); up(root); } void modify(int p,int v) { split(p,p); val[key_value]=v; } void run(int x) { if(!x)return; run(lc); if(val[x]!=inf && val[x]!=-inf) { //printf("%d ",val[x]); a[++all]=val[x]; } run(rc); } void init() { root=newnode(-inf,0); ch[root][1]=newnode(inf,root); up(ch[root][1]); up(root); } void test() { init(); int T=getint(); while(T--) { int opt=getint(); if(opt==1) { int x=getint(); int y=getint(); insert(x,y); } else if(opt==2) { int x=getint(); int y=getint(); modify(x,y); } run(root); puts(""); } } char opt[20]; int f[maxn]; db slope(int j,int k) { return (db)(q[j]-q[k])/(db)(p[j]-p[k]); } int qu[maxn]; int l,r; inline void print(ll x) { if(!x){putchar('0');return;} if(x>=10)print(x/10); putchar('0'+x%10); } void solve() { init(); for(int i=1;i<=m;i++) { scanf("%s",opt); if(opt[0]=='C') { int x=getint(); int y=getint(); modify(x+1,y); } else { int x=getint(); int y=getint(); insert(x+1,y); } } run(root); l=1; for(int i=1;i<=n;i++) { p[i]=getint(); q[i]=getint(); } for(int i=2;i<=n;i++) { ll mx=0; for(int j=1;j<i;j++) { mx=max((ll)q[j]-(ll)a[i]*(ll)p[j],mx); } print(mx); putchar('\n'); } }}namespace another_brute_force{ #define lc ch[x][0] #define rc ch[x][1] #define key_value ch[ch[root][1]][0] const int maxn=900005; int pre[maxn]; int ch[maxn][2]; int val[maxn]; int size[maxn]; int root; int tot; int all; int a[maxn]; int p[maxn]; int q[maxn]; inline int newnode(const int& v,const int& fa) { int x=++tot; lc=rc=0; pre[x]=fa; val[x]=v; size[x]=1; return x; } inline void up(int x) { size[x]=size[lc]+size[rc]+1; } void rotate(int x) { int y=pre[x]; int f=(ch[y][0]==x); pre[x]=pre[y]; pre[ch[x][f]]=y; ch[y][!f]=ch[x][f]; if(pre[y]) { ch[pre[y]][ch[pre[y]][1]==y]=x; } pre[y]=x; ch[x][f]=y; up(y); up(x); } void splay(int x,int goal) { while(pre[x]!=goal) { int y=pre[x],z=pre[y]; if(pre[y]!=goal){ if((ch[z][0]==y)^(ch[y][0]==x))rotate(x); else rotate(y); } rotate(x); } up(x); if(goal==0)root=x; } int findk(int x,int k){ if(!x)return 0; if(k<=size[lc])return findk(lc,k); if(k>size[lc]+1)return findk(rc,k-size[lc]-1); return x; } void split(int l,int r) { splay(findk(root,l),0); splay(findk(root,r+2),root); } void insert(int p,int v) { split(p,p-1); key_value=newnode(v,ch[root][1]); up(ch[root][1]); up(root); } void modify(int p,int v) { split(p,p); val[key_value]=v; } void run(int x) { if(!x)return; run(lc); if(val[x]!=inf && val[x]!=-inf) { //printf("%d ",val[x]); a[++all]=val[x]; } run(rc); } inline void init() { root=newnode(-inf,0); ch[root][1]=newnode(inf,root); up(ch[root][1]); up(root); } void test() { init(); int T=getint(); while(T--) { int opt=getint(); if(opt==1) { int x=getint(); int y=getint(); insert(x,y); } else if(opt==2) { int x=getint(); int y=getint(); modify(x,y); } run(root); puts(""); } } char opt[20]; ll f[maxn]; inline db slope(int j,int k) { return (db)(q[j]-q[k])/(db)(p[j]-p[k]); } int qu[maxn]; int l,r; inline void print(ll x) { if(!x){putchar('0');return;} if(x>=10)print(x/10); putchar('0'+x%10); } void solve() { init(); for(int i=1;i<=m;i++) { scanf("%s",opt); if(opt[0]=='C') { int x=getint(); int y=getint(); modify(x+1,y); } else { int x=getint(); int y=getint(); insert(x+1,y); } } run(root); l=1; for(int i=1;i<=n;i++) { if(i!=1) { int lll=l; int rr=r; while(lll<rr) { int mid=(lll+rr)>>1; if(slope(qu[mid+1],qu[mid])>a[i]) { lll=mid+1; } else { rr=mid; } } ll temp=-(ll)a[i]*(ll)p[qu[lll]]+(ll)q[qu[lll]]; temp=max(temp,0ll); print(temp); //puts(""); putchar('\n'); //printf("%lld\n",temp); } p[i]=getint(); q[i]=getint(); while(l<r && slope(qu[r],qu[r-1])<slope(qu[r],i))r--; qu[++r]=i; } } }//expected score 100int main(){ freopen("hoodle.in","r",stdin); freopen("hoodle.out","w",stdout); n=getint();m=getint(); /**/ if(n<=10000)brute_force::solve(); else /**/ another_brute_force::solve(); return 0;}
- 2015湖南省队集训DAY4——hoodle
- 2015湖南省队集训DAY3——Light
- 2015湖南省队集训DAY6——B题(BZOJ4179)
- 2015湖南省队集训DAY8——梦工厂
- 福建省队集训被虐记——DAY4
- 省队集训DAY4
- 省队集训Round3 DAY4
- 暑期集训—day4—第一次暑期训练
- 湖南集训Day4
- ACM集训day4
- 沈阳集训day4
- 雅礼集训Day4
- 北京集训DAY4
- 湖南集训 Day4
- 【集训Day4 动态规划】蛙人
- IMWeb提升营 —Day4
- 陕西省集训 day4(搜索下)
- 【泉州一中国庆集训day4】破解
- Rectangle Area
- MySQL优化之——优化
- Haskell趣学指南学习日记(1)
- SecureCRT 连接sqlplus删除键失效解决方法
- 带下拉刷新的瀑布流 不会oom
- 2015湖南省队集训DAY4——hoodle
- 《Opencv 入门教程》
- leetcode系列(9)miniStack,stack_to_queue, queue_to_stack
- 大阪中文离线地图App上线
- OpenGL学习脚印: 投影矩阵的推导
- HDU 1074 Doing Homework (状压DP + 路径记录)
- 一.Spring学习之旅----初识Spring
- 文章标题
- 简单的模拟多线程引用计数原理