zoukankan      html  css  js  c++  java
  • [NOI2008]糖果雨

    bzoj1062【Noi2008】糖果雨

    首先给出的颜色没有用。

    估计要用数据结构。而线段难以维护。

    考虑把线段变成点

    T是单增的。

    所以询问的时候,存在的线段都可能贡献答案。

    那些线段的位置如果可以统一一下就好了。

    发现线段2*len一个循环

    思路:把所有的线段移动到l=0

    或者说,考虑l=0的时候,时间是多少

    横坐标:x=(ti-d*l)%(2*len)(这个时间仅仅为了相对关系表示方便,实际上,这个线段可能根本不会在这个时间出现,不过没有关系)

    纵坐标:y=r-l

    这样的好处是,线段都是从l=0向右移动了

    实际上坐标是多少,就意味着距离0还有多远

    (看上面博客有图)

    然后对于询问的t

    分成一个图形,计算点的个数

    转化为平行四边形

    转化为矩形

    二维树状数组维护

    为了避免讨论

    可以直接分成四块。不合法的直接面积返回0

    注意时间轴的下标是从[0,2*len-1]的

    所以树状数组还要集体平移1

    细节较多。边界有些恶心

    r==len的时候还要特别防止一个点统计两遍。

    代码:

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=200000+5;
    const int M=2020;
    int n,len;
    int mod;
    struct node{
        int x,y1,y2;
    }p[N];
    int cnt;
    int co[1000000+5];
    struct at{
        int f[2*M][4*M];
        void add(int x,int y,int c){
            //swap(x,y);
            while(x<2010){
                int tmp=y;
                while(tmp<4010){
                    f[x][tmp]+=c;
                    tmp+=tmp&(-tmp);
                }
                x+=x&(-x);
            }
        }
        int query(int x,int y){
            //swap(x,y);
            if(x<0||y<0) return 0;
            ++x,++y;
            if(x>=2*len) x=2*len;
            if(y>=4*len) y=4*len;
            int ret=0;
        //    cout<<" x y "<<x<<" "<<y<<endl;
            while(x){
                int tmp=y;
                while(tmp){
                    ret+=f[x][tmp];
                    tmp-=tmp&(-tmp);
                }
                x-=x&(-x);
            }
            return ret;
        }
    }t1,t2;
    int get(int x1,int y1,int x2,int y2,int c){
    //    cout<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<" "<<c-1<<endl;
        if(c==1){
            int ret=t1.query(x2,y2)+t1.query(x1-1,y1-1)-t1.query(x1-1,y2)-t1.query(x2,y1-1);
        //    cout<<" ret "<<ret<<endl;
        return ret;
        }else{
            int ret=t2.query(x2,y2)+t2.query(x1-1,y1-1)-t2.query(x1-1,y2)-t2.query(x2,y1-1);
        //    cout<<" ret "<<ret<<endl;
        return ret;
        }
    }
    int sol(int t,int l,int r){
        int d=(r==len);
        return get(t,t+l,t+r,4*len,1)+get(0,t+l-mod,t+r-mod-d,4*len,1)
            +get(t-r,l-t+mod,t-1,4*len,2)+get(t-r+mod+d,l-t,mod-1,4*len,2);
    }
    int main(){
        rd(n);rd(len);
        int op,t,c,l,r,d;
        mod=2*len;
        while(n--){
            rd(op);
            if(op==1){
                rd(t);rd(c);rd(l);rd(r);rd(d);
                ++cnt;
                p[cnt].x=(t-d*l+mod)%mod;
                p[cnt].y1=(r-l+p[cnt].x);
                p[cnt].y2=(r-l-p[cnt].x+mod);
            //    cout<<" point "<<p[cnt].x<<" "<<p[cnt].y1<<" || "<<p[cnt].y2<<endl;
                co[c]=cnt;
                t1.add(p[cnt].x+1,p[cnt].y1+1,1);
                t2.add(p[cnt].x+1,p[cnt].y2+1,1);
            }else if(op==2){
                rd(t);rd(l);rd(r);
                t%=mod;
                printf("%d
    ",sol(t,l,r));
            }else{
                rd(t);rd(c);
                t1.add(p[co[c]].x+1,p[co[c]].y1+1,-1);
                t2.add(p[co[c]].x+1,p[co[c]].y2+1,-1);
                co[c]=0;
            }
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/1/8 14:12:04
    */

    转化还是鬼斧神工

    方向就是抓住时间单增,统一出发位置考虑,mod意义下处理,线段变成点,方便维护。

    不规则图形转化,坐标翻转。

    同时避免讨论的小trick也不错。(这还是对水平要求比较高的)

  • 相关阅读:
    小作业5
    小作业4
    Matplotlib基础
    Numpy学习笔记(下篇)
    Numpy学习笔记(上篇)
    机器学习的经典算法与应用
    opencv学习笔记D01
    Markdown新手入门
    python之生成器yeild
    pyinstaller打包.py程序为.exe操作指南
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10240282.html
Copyright © 2011-2022 走看看