2015湖南省队集训DAY4——hoodle

原创 2015年07月07日 21:09:51

弹珠 (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 100
int 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湖南省队集训DAY8——梦工厂

梦工厂 (yume.cpp/c/pas)Time Limit: 1 s Memory Limit: 128 M 问题描述「有时候用烂了的名字也会别有深意」 ——摘自EN 语录 “这里是...

2015湖南省队集训DAY6——B题(BZOJ4179)

题面挺扯的,我就直接说人话算了。 题目大意:给你若干个病毒串,问你能不能构造出长度大于n的字符串使其中不出现任何一个字符串。 多组数据,总文件大小小于1M 题解: 联动:BZOJ2938 基...

2015湖南省队集训DAY3——Light

Light【问题描述】“若是万一琪露诺(俗称 rhl)进行攻击,什么都好,冷静地回答她的问题来吸引 对方表现出兴趣的话,那就慢慢地反问。在她考虑答案的时候,趁机逃吧。就算是很简 问题,她一定也答不...

2015湖南省选集训DAY5——work(BZOJ4177)

DescriptionMike有一个农场,这个农场n个牲畜围栏,现在他想在每个牲畜围栏中养一只动物,每只动物可以是牛或羊,并且每个牲畜围栏中的饲养条件都不同,其中第i个牲畜围栏中的动物长大后,每只牛可...

福建省队集训被虐记——DAY4

啊啊啊啊啊啊第四天考的是我最不擅长的图论……
  • zhb1997
  • zhb1997
  • 2014年07月16日 22:07
  • 367

省队集训Round3 DAY4

T2 题解 讲序列分成三部分,大根堆,缓冲区s,小根堆。 任意时刻保证mid在缓冲区中,并且尽量保证大根堆和小根堆的大小尽量相等。 均摊时间复杂度为O(nlogn/s+n)O(nlog...

noi2017江苏省队集训day1

  • 2017年08月15日 14:18
  • 97KB
  • 下载

CCNU ACM 2016夏季集训·day4模拟赛(!!!)

做毛子题,你会感觉你辜负了你的基因;做美帝题,你会感觉你辜负了你的算法老师;做天朝题,你会觉得你辜负了你的小学语文老师、小学数学老师、小学英语老师,以及高中那个教你c艹的前辈……(被各种输入格式、输出...
  • fybmain
  • fybmain
  • 2016年07月15日 13:47
  • 151

[(可持久化)字典树 优化建图][2-SAT] LOJ#6036. && 雅礼集训 2017 Day4. 编码

老早以前的坑了 貌似好多地方都有这个题 因为每个串都只有一个问号,问号可取0可取1,这就是一个经典的2-SAT模型 但是直接做的话,边数是n2n^2级别的,不过因为是01串,可以用可持久化字典树...
  • Coldef
  • Coldef
  • 2017年07月13日 17:05
  • 292

[2017雅礼集训]day4 T1 洗衣服 贪心

其实我也不知到为什么洗衣服和晒衣服是独立的。。。 既然是独立的,我们就贪心的把每件衣服最快能洗完的时刻和最快能烘干的时刻分别先预处理出来,就是贪心的往当前结束时间最早的机器里放(堆维护)。 然后两...
  • DOFYPXY
  • DOFYPXY
  • 2017年04月17日 20:15
  • 232
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:2015湖南省队集训DAY4——hoodle
举报原因:
原因补充:

(最多只允许输入30个字)