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;
}

相关文章推荐

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

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

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

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

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

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

noi2017江苏省队集训day1

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

[树的同构][二分][可并堆维护哈希] LOJ#6066 || BZOJ4928 && 2017 山东一轮集训 Day3. 第二题

这题一看就可以二分 那么解决这题的关键就变成了怎么对树进行哈希,以及怎么快速维护哈希值 想了一个下午想了一个比较靠谱的哈希方法。 用一个p进制数(p>n且为质数)来表示每一个节点,这个数有dep...
  • Coldef
  • Coldef
  • 2017年07月11日 18:07
  • 222

5月集训Day3考试

小P的2048:暴力模拟,小P的单调数列seq:dp裸题,小P的生成树mst:最大向量生成树...

[计数][容斥] LOJ#6065 || BZOJ4927 && 2017 山东一轮集训 Day3. 第一题

因为要选6根木棒,发现肯定是1,1,2,2或1,1,1,3形式。 可以枚举2和3的部分,然后推一推,容斥容斥就可以了 但是细节贼多#include #include #include #in...
  • Coldef
  • Coldef
  • 2017年07月11日 17:48
  • 245

博士的计算器 [师大集训 Day 3]

博士的计算器

2017暑期集训 Day 3 搜索与并查集

A - 食物链[solution] 并查集新操作! 维护决策的矛盾信息,每次决策之间的选择是互相矛盾的 每个动物可能为三种情况:A、B、C,i代表第i种动物是A类动物,i+n代表第i种动物是B类...
  • Yancy_
  • Yancy_
  • 2017年07月14日 22:32
  • 81

ACM集训day15——DP

7.2501背包引入讲了动态规划DP首先会有个疑问:贪心思想不能做吗?确实不能。01背包放东西只有放或不放,没有像贪心题那样可以放几分之几。而且,举个例子:3个物品大小分别是3,3,7,价值分别是6,...
  • yzzzjc
  • yzzzjc
  • 2016年07月27日 22:06
  • 80
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:2015湖南省队集训DAY3——Light
举报原因:
原因补充:

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