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;}
0 0
原创粉丝点击