• 题解 洛谷 P4203 【[NOI2008]糖果雨】


    发现任何时刻不会出现两片颜色相同的云朵,因此云朵的颜色是不用考虑的,询问即为区间内有多少个云朵。

    因为云朵的运动是在天空中往返的,具有周期性,且每个云朵运动速度都相同,所以可以用二元组 ((time,lenth)) 来表示一个云朵,(time) 为该云朵左端点位于左边界时的时刻,即 (t-ld mod 2len)(lenth) 为该云朵的长度,即 (r-l),发现每个云朵都能用二维平面上的点 ((x,y)) 来表示。

    接着考虑如何解决询问 ((t,l,r)),首先对 (t) 转化为 (t mod 2len)。然后通过分类讨论来找到对于该询问在二维平面上对应的位置。设云朵的坐标为 ((x,y)),得:

    (t geqslant x) 时,该云朵要到达询问的时刻还需再经过一段时间,经过这些时间后云朵的左端点要在询问的右端点左边,即 (t-x leqslant r),云朵的右端点要在询问的左端点右边,即 (t-x+y geqslant l)

    (t < x) 时,该云朵已经超过询问的时刻,因此其需要时光倒流,因为运动的周期性,其还是向右运动,把这些时间倒流后云朵的左端点要在询问的右端点左边,即 (x-t leqslant r),云朵的右端点要在询问的左端点右边,即 (x-t+y geqslant l)

    综上所述得询问在二维平面上对应的位置为 (t-r leqslant x leqslant t+r,| x-t | +y geqslant l),在平面上画出图来得:

    发现图像为两个对称的五边形,若其超出了边界,就在另一端补上来,对于该图像不好进行统计,因此还需再进行转化,将其补成平行四边形得:

    然后考虑对这两个平行四边形转化为矩形来进行统计,因为是询问存在性,而不是面积之类的信息,所以对于询问的范围进行转化,对于每个云朵的坐标也进行转化,然后进行询问就是合法的。对于右边向右倾斜的平行四边形,对其应用变换 ((x,y) Rightarrow (x,x+y)),对于左边向左倾斜的平行四边形,对其应用变换 ((x,y) Rightarrow (x,y-x+2len)),这里加上 (2len) 的原因是防止出现负坐标。然后对于这两个平行四边形分别用两个二维树状数组来维护,每个云朵在树状数组上进行加点删点时也应用相应的变换即可。

    注意到当询问出现 (r=len) 的情况时,(t-r)(t+r) 这两个位置会算重,因此需要特判。

    #include<bits/stdc++.h>
    #define maxn 4010
    #define maxm 1000010
    #define lowbit(x) (x&(-x))
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,len;
    struct node
    {
        int x,y;
    }p[maxm];
    struct BIT
    {
        int t[maxn][maxn];
        void update(int x,int y,int v)
        {
            for(int i=x+1;i<=2*len;i+=lowbit(i))
                for(int j=y+1;j<=4*len;j+=lowbit(j))
                    t[i][j]+=v;
        }
        int ask(int x,int y)
        {
            if(x<0||y<0) return 0;
            int v=0;
            for(int i=min(x+1,2*len);i;i-=lowbit(i))
                for(int j=min(y+1,4*len);j;j-=lowbit(j))
                    v+=t[i][j];
            return v;
        }
        int query(int x1,int y1,int x2,int y2)
        {
            return ask(x2,y2)-ask(x2,y1-1)-ask(x1-1,y2)+ask(x1-1,y1-1);
        }
    }T1,T2;
    int main()
    {
        read(n),read(len);
        for(int i=1;i<=n;++i)
        {
            int opt,t,c,l,r,d,v=0;
            read(opt);
            if(opt==1)
            {
                read(t),read(c),read(l),read(r),read(d);
                p[c].x=(t-l*d+2*len)%(2*len),p[c].y=r-l;
                T1.update(p[c].x,p[c].x+p[c].y,1),T2.update(p[c].x,p[c].y-p[c].x+2*len,1);
            }
            if(opt==2)
            {
                read(t),read(l),read(r),d=(r==len),t%=2*len;
                v+=T1.query(t,t+l,t+r-d,4*len);
                v+=T1.query(0,t+l-2*len,t+r-2*len,4*len);
                v+=T2.query(t-r+d,l-t+2*len,t-1,4*len);
                v+=T2.query(t-r+2*len,l-t,2*len,4*len);
                printf("%d
    ",v);
            }
            if(opt==3)
            {
                read(t),read(c);
                T1.update(p[c].x,p[c].x+p[c].y,-1),T2.update(p[c].x,p[c].y-p[c].x+2*len,-1);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    MarkdownPad 2 HTML 渲染错误解决办法
    ubuntu 修改用户名和密码
    在浏览器输入http://127.0.0.1/phpmyadmin,出现not found界面
    MySQL出现Incorrect integer value: '' for column 'id' at row 1解决方法
    Ubuntu中查找文件
    Python+Selenium--控制浏览器控制条
    关于Python+selenium 定位浏览器弹窗元素
    python中安装request模块
    Python+Selenium--cookie处理
    JS控制HTML元素的显示和隐藏
  • 原文地址:https://www.cnblogs.com/lhm-/p/13569337.html
Copyright © 2020-2023  润新知