2015湖南省队集训DAY3——Light

原创 2015年07月07日 20:57:48

Light

【问题描述】

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

天空中出现了许多的北极光,这些北极光组成了一个长度为n的正整数数列 a[i],远
魔书上记载到:2 个位置的 graze 值为两者位置差与数值差的和:
graze(x,y)=|x-y|+|a[x]-a[y]|。
要想破解天罚,就必须支持 2种操作(k 都是正整数):
Modify x k:将第 x个数的值修改为k。
Query x k:询问有几个 i满足graze(x,i)<=k。
由于从前的天罚被圣王lmc破解了,所以rhl改进了她的法术,询问不仅要考虑当
列,还要考虑任意历史版本,即统计任意位置上出现过的任意数值与当前的a[x]的 graz
<=k的对数。(某位置多次修改为同样的数值,按多次统计)

【输入格式】

第1行两个整数 n,q。分别表示数列长度和操作数。
第2行 n个正整数,代表初始数列。
第3~q+2 行每行一个操作。

【输出格式】

对于每次询问操作,输出一个非负整数表示答案。

【样例输入】

3 5
2 4 3
Query 2 2
Modify 1 3
Query 2 2
Modify 1 2
Query 1 1

【样例输出】

2
3
3

【数据规模与约定】

n40000,m60000,ai100000

题解:
出题人的题解真是简单(虽然题目也很简单)
“直接线段树套平衡树就可以了”
傻逼k-d树调了快俩小时,这搞腿子。
因为询问是与给定点的曼哈顿距离小于给定值的点个数,这个可以把坐标转换一下,像这样:

x=x+yy=xy

然后询问就变成一个正方形了。
代码在这:
(因为是考场代码所以有暴力的特判和一些奇怪的注释,而且不知道为什么就有6.6k了)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef double db;

const int inf=300005;

int getint()
{
    int f=1,g=0;char c=getchar();
    while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c<='9' && c>='0')g=(g<<3)+(g<<1)+c-'0',c=getchar();
    return f*g;
}

int n;
int q;

namespace brute_force{

    const int maxn=200005;

    vector<int> a[maxn];
    int b[maxn];

    bool check()
    {
        return q<=99;
    }

    char opt[20];

    void solve()
    {
        for(int i=1;i<=n;i++)
        {
            a[i].push_back(getint());
            b[i]=a[i][0];
        }

        int x,y;

        for(int i=1;i<=q;i++)
        {
            scanf("%s",opt);
            if(opt[0]=='M')
            {
                x=getint();
                y=getint();
                a[x].push_back(y);
                b[x]=y;
            }           
            if(opt[0]=='Q')
            {
                x=getint();
                y=getint();
                int cnt=0;
                for(int j=1;j<=n;j++)
                {
                    for(int l=0;l<a[j].size();l++)
                    {
                        if(abs(x-j)+abs(b[x]-a[j][l])<=y)
                        {
                            cnt++;
                        }
                    }
                }
                printf("%d\n",cnt);
            }
        }       
    }

}

namespace another_brute_force{

    const int maxn=160005;

    struct node{
        int d[2];
        int min[2];
        int max[2];
        int cnt;
        int size;
        int l,r;

        int& operator [] (const unsigned int& num)
        {
            return d[num];
        }       

    };  

    node t[maxn];
    node p[maxn];

    int dim;
    int tot;

    #define ls t[x].l
    #define rs t[x].r

    #define lc t[t[x].l]
    #define rc t[t[x].r]

    #define mid (l+r>>1)

    bool cmp (const node& n1,const node& n2)
    {
        return n1.d[dim]<n2.d[dim];
    }

    struct kd_tree
    {
        node T;
        int root;

        void update(int x)
        {
            t[x].size=t[x].cnt;
            t[x].min[0]=t[x].max[0]=t[x][0];
            t[x].min[1]=t[x].max[1]=t[x][1];
            for(int i=0;i<2;i++)
            {
                if(ls)
                {
                    t[x].max[i]=max(t[x].max[i],lc.max[i]);
                    t[x].min[i]=min(t[x].min[i],lc.min[i]);
                }
                if(rs)
                {
                    t[x].max[i]=max(t[x].max[i],rc.max[i]);
                    t[x].min[i]=min(t[x].min[i],rc.min[i]);
                }
            }
            if(ls)t[x].size+=lc.size;
            if(rs)t[x].size+=rc.size;           
        }
        /**/
        void build(int &x,int l,int r,int now)
        {
            if(l>r)return;
            dim=now;
            nth_element(p+l,p+mid,p+r,cmp);

            x=mid;
            t[x].cnt=1;
            t[x].size=1;
            for(int i=0;i<2;i++)
            {
                t[x][i]=t[x].min[i]=t[x].max[i]=p[x][i];
            }
            build(ls,l,mid-1,now^1);
            build(rs,mid+1,r,now^1);
            update(x);          
        }
        void insert(int& x,int now)
        {
            if(!x)
            {
                x=++tot;
                t[x]=T;
                return;
            }
            if(T[0]==t[x][0] && T[1]==t[x][1])
            {
                t[x].cnt++;
                t[x].size++;
                return;
            }
            if(T[now]>t[x][now])
            {
                insert(rs,now^1);
                update(x);
            }
            else
            {
                insert(ls,now^1);
                update(x);
            }
        }

        int k;
        int The_Answer;
        /*
        bool check(int x)
        {
            int left=T[0]-k;
            int right=T[0]+k;
            int up=T[1]+k;
            int down=T[1]-k;
            if(down>t[x].max[1] || up<t[x].min[1] || left>t[x].max[0] || right<t[x].min[0])
            return false;
            return true;
        }

        int get(int x)
        {
            int left=T[0]-k;left=max(0,t[x].max[0]-left);
            int right=T[0]+k;right=max(0,right-t[x].min[0]);
            int up=T[1]+k;up=max(0,up-t[x].min[1]);
            int down=T[1]-k;down=max(0,t[x].max[1]-down);
            return min(min(left,right),min(up,down));
        }

        void query(int x)
        {
            if(!x)return;
            if(max(abs(t[x].min[0]-T[0])+abs(t[x].min[1]-T[1]),abs(t[x].max[0]-T[0])+abs(t[x].max[1]-T[1]))<=k
            && max(abs(t[x].min[0]-T[0])+abs(t[x].max[1]-T[1]),abs(t[x].min[1]-T[1])+abs(t[x].max[0]-T[0]))<=k)
            {
                The_Answer+=t[x].size;
                return;
            }
            /*
            if(min(abs(t[x].min[0]-T[0])+abs(t[x].min[1]-T[1]),abs(t[x].max[0]-T[0])+abs(t[x].max[1]-T[1]))>k
            && min(abs(t[x].min[0]-T[0])+abs(t[x].max[1]-T[1]),abs(t[x].min[1]-T[1])+abs(t[x].max[0]-T[0]))>k
            &&(t[x].min[0]>T[0] || t[x].max[0]<T[0] || t[x].min[1]<T[1] || t[x].max[1]>T[1]))
            *
            if(!check(x))
            {
                return;
            }

            if(abs(t[x][0]-T[0])+abs(t[x][1]-T[1])<=k)
            {
                The_Answer+=t[x].cnt;
            }
/*          
int tl=min( min(abs(lc.min[0]-T[0])+abs(lc.min[1]-T[1]),abs(lc.max[0]-T[0])+abs(lc.max[1]-T[1])),
            min(abs(lc.min[0]-T[0])+abs(lc.max[1]-T[1]),abs(lc.max[0]-T[0])+abs(lc.min[1]-T[1])));

int tr=min( min(abs(rc.min[0]-T[0])+abs(rc.min[1]-T[1]),abs(rc.max[0]-T[0])+abs(rc.max[1]-T[1])),
            min(abs(rc.min[0]-T[0])+abs(rc.max[1]-T[1]),abs(rc.max[0]-T[0])+abs(rc.min[1]-T[1])));
*
            int tl=get(ls);
            int tr=get(rs);
            if(tl<=tr)
            {
                if(tl<=k)query(ls);
                if(tr<=k)query(rs);
            }
            else
            {
                if(tr<=k)query(rs);
                if(tl<=k)query(ls);
            }
        }
        */

        node T1,T2;

        void query(int x)
        {
            if(!x)return;
            if(t[x].max[0]<T1[0] || t[x].min[0]>T2[0] || t[x].max[1]<T1[1] || t[x].min[1]>T2[1])return;
            if(t[x].max[0]<=T2[0] && t[x].min[0]>=T1[0] && t[x].max[1]<=T2[1] && t[x].min[1]>=T1[1])
            {
                The_Answer+=t[x].size;
                return;
            }
            if(t[x][0]>=T1[0] && t[x][0]<=T2[0] && t[x][1]>=T1[1] && t[x][1]<=T2[1])
            {
                The_Answer+=t[x].cnt;               
            }

            int tl=min(min(abs(T1[0]-lc.max[0]),abs(T2[0]-lc.min[0])),min(T1[1]-lc.max[1],T2[1]-lc.min[1]));
            int tr=min(min(abs(T1[0]-rc.max[0]),abs(T2[0]-rc.min[0])),min(T1[1]-rc.max[1],T2[1]-rc.min[1]));

            if(tl<=tr)
            {
                if(tl<=k)query(ls);
                if(tr<=k)query(rs);
            }
            else
            {
                if(tr<=k)query(rs);
                if(tl<=k)query(ls);
            }
        }

        void ins(int x,int y)
        {
            T[0]=T.min[0]=T.max[0]=x;
            T[1]=T.min[1]=T.max[1]=y;
            T.size=T.cnt=1;
            T.l=T.r=0;
            insert(root,0);
        }
        int que(int x,int y,int kk)
        {
            T1[0]=max(-inf,x-kk);
            T2[0]=min(inf,x+kk);
            T1[1]=max(-inf,y-kk);
            T2[1]=min(inf,y+kk);
            k=kk;The_Answer=0;
            query(root);
            return The_Answer;
        }
    }kdtree;

    int b[maxn];

    char opt[20];

    void solve()
    {
        kdtree.The_Answer=0;
        for(int i=1;i<=n;i++)
        {
            b[i]=getint();
            //kdtree.ins(i+b[i],i-b[i]);
            p[i][0]=i+b[i];
            p[i][1]=i-b[i];
        }
        kdtree.build(kdtree.root,1,n,0);
        tot=n;
        int x,y;
        for(int i=1;i<=q;i++)
        {
            scanf("%s",opt);
            if(i==10000)
            {
                i++;
                i--;
            }
            if(opt[0]=='Q')
            {
                x=getint();
                y=getint();
                printf("%d\n",kdtree.que(x+b[x],x-b[x],y));
            }
            else
            {
                x=getint();
                y=getint();
                b[x]=y;
                kdtree.ins(x+b[x],x-b[x]);
            }
        }
    }
}
//expected score 100
int main()
{
    freopen("light.in","r",stdin);
    freopen("light.out","w",stdout);

    n=getint();
    q=getint();
    /**/
    if(brute_force::check())
    {
        brute_force::solve();
    }
    else
    /**/
    {
        another_brute_force::solve();
    }

    return 0;
}

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

昨天没写……今天补上吧
  • zhb1997
  • zhb1997
  • 2014年07月15日 22:55
  • 562

2015湖南省队集训DAY8——梦工厂

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

数据结构优化连边

什么是线段树连边对于一类题目,它们建出来的图好大好大,这时候通常可以利用线段树(大多数时候是可持久化线段树)来进行优化连边,保证点的连通性不变,路径权值信息不变。例题1:湖南集训2014Jabberw...
  • WerKeyTom_FTD
  • WerKeyTom_FTD
  • 2016年01月15日 19:55
  • 541

[清华集训2015]V

题目大意给出一个序列a,现在有五种操作 1、把[l,r]每个ai加上x 2、把[l,r]每个ai变成x 3、把[l,r]每个ai变成max(ai-x,0) 4、询问目前ai的值 5、询问ai...
  • WerKeyTom_FTD
  • WerKeyTom_FTD
  • 2016年10月31日 16:36
  • 738

2015湖南省队集训DAY4——hoodle

弹珠 (hoodle)【问题描述】D.Ash 是一个喜欢玩弹珠的小男孩,他有一盒五颜六色的弹珠,在阳光的照射下非 美丽。 同样,他喜欢聆听弹珠相碰时的清脆声音。 经过他的观察,每个弹珠有三个参数...
  • Starry__Night
  • Starry__Night
  • 2015年07月07日 21:09
  • 610

省队集训DAY3

T1 题解 一共要使用六根木棍,那么分割的方法就两种{1,1,1,3},{1,1,2,2} 那么关键就是要计算2,3的数量。 cnt1[i]表示每种长度的木棍的方案数 cnt2[i]...
  • clover_hxy
  • clover_hxy
  • 2017年08月19日 20:34
  • 133

#164. 【清华集训2015】V

线段树维护 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ...
  • sxb_201
  • sxb_201
  • 2016年03月13日 20:33
  • 311

湖南集训Day5

T1果然是回文自动机(树),zyh讲了一下然而还是听不懂。 下午的网络流看各路神犇秒题,分分钟口胡出来,真是6的不行啊,我这种弱渣只能看看,顺便围观一堆小号233333。 晚上好像整栋楼都在刷Go...
  • nlj1999
  • nlj1999
  • 2015年12月31日 00:00
  • 185

uoj164. 【清华集训2015】V

Picks博士观察完金星凌日后,设计了一个复杂的电阻器。为了简化题目,题目中的常数与现实世界有所不同。 这个电阻器内有编号为 1∼n1∼n 的 nn 个独立水箱,水箱呈圆柱形,底面积为 1 m21 ...
  • CRZbulabula
  • CRZbulabula
  • 2017年01月09日 11:05
  • 450

省队集训Round2 DAY3

T3 题解 要求每一个时间每条边只能有一个人经过,每个人在到达终点前的任意时刻都不能停止。 那么我们可以二分一个最晚的时间mid,然后建mid层结点,每条有向边x->y从i层的x结点...
  • clover_hxy
  • clover_hxy
  • 2017年08月20日 11:17
  • 126
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:2015湖南省队集训DAY3——Light
举报原因:
原因补充:

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