zoukankan      html  css  js  c++  java
  • HDU 6089 Rikka with Terrorist (线段树)

    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=6089

    题解

    这波强行维护搞得我很懵逼。。。
    扫描线,只考虑每个点能走到左上方(不包括正上方,但包括正左方)的哪些点,然后旋转四次坐标系处理
    所有询问和操作点按照先(x)(y)坐标的顺序排序,然后枚举每一行,按(y)从小到大的顺序枚举这一行每个点
    对于一个询问点找出前面最后一个操作点,那么要求的就是一个矩形减去一个区间内所有后缀最大值的和
    然后这个东西可以用线段树直接维护,记录个区间最大值然后pushup的时候二分
    操作点就相当于单点修改
    时间复杂度(O(nlog^2n)).

    代码

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<utility>
    #include<algorithm>
    #define llong long long
    #define pll pair<llong,llong>
    #define mkpr make_pair
    using namespace std;
     
    const int N = 1e5;
     
    struct SegmentTree
    {
        struct SgTNode
        {
            llong maxi,psum;
        } sgt[(N<<2)+3];
        void clear(int u,int le,int ri)
        {
            sgt[u].maxi = sgt[u].psum = 0;
            if(le==ri) return;
            int mid = (le+ri)>>1;
            clear(u<<1,le,mid); clear(u<<1|1,mid+1,ri);
        }
        llong calc(int u,int le,int ri,llong x)
        {
            if(le==ri) {return sgt[u].maxi<x ? x : sgt[u].maxi;}
            int mid = (le+ri)>>1;
            if(sgt[u<<1|1].maxi<x) {return calc(u<<1,le,mid,x)+x*(ri-mid);}
            else {return sgt[u].psum-sgt[u<<1|1].psum+calc(u<<1|1,mid+1,ri,x);} //Note here!
        }
        void pushup(int u,int le,int ri)
        {
            int mid = (le+ri)>>1;
            sgt[u].maxi = max(sgt[u<<1].maxi,sgt[u<<1|1].maxi);
            sgt[u].psum = calc(u<<1,le,mid,sgt[u<<1|1].maxi)+sgt[u<<1|1].psum;
        }
        void modify(int u,int le,int ri,int pos,llong x)
        {
            if(le==pos && ri==pos) {sgt[u].maxi = sgt[u].psum = x; return;}
            int mid = (le+ri)>>1;
            if(pos<=mid) {modify(u<<1,le,mid,pos,x);}
            else {modify(u<<1|1,mid+1,ri,pos,x);}
            pushup(u,le,ri);
        }
        pll query(int u,int le,int ri,int lb,int rb,llong x)
        {
            if(lb>rb) {return make_pair(0,0);}
            if(le>=lb && ri<=rb) {return make_pair(max(sgt[u].maxi,x),calc(u,le,ri,x));}
            int mid = (le+ri)>>1;
            if(rb<=mid) {return query(u<<1,le,mid,lb,rb,x);}
            else if(lb>mid) {return query(u<<1|1,mid+1,ri,lb,rb,x);}
            else
            {
                pll retr = query(u<<1|1,mid+1,ri,lb,rb,x);
                pll retl = query(u<<1,le,mid,lb,rb,retr.first);
                return mkpr(retl.first,retl.second+retr.second);
            }
        }
    } sgt;
     
    struct Query
    {
        int x,y,id;
        Query() {}
        Query(int _x,int _y,int _id) {x = _x,y = _y,id = _id;}
        bool operator <(const Query &arg) const
        {
            return x<arg.x || (x==arg.x && y<arg.y);
        }
    };
    llong fans[N+3];
    int mx[N+3];
     
    namespace Solve
    {
        Query qr[(N<<1)+3];
        int q;
        int nx,ny;
        void addquery(int x,int y,int id) {q++; qr[q] = Query(x,y,id);}
        void solve()
        {
            sort(qr+1,qr+q+1); int j = 1; while(j<=q && qr[j].x==0) j++;
            for(int i=1; i<=nx; i++)
            {
                int k = 0;
                while(j<=q && qr[j].x==i)
                {
                    if(qr[j].id==0)
                    {
                        sgt.modify(1,1,ny,qr[j].y,i);
                        k = qr[j].y; mx[qr[j].y] = i;
                    }
                    else
                    {
                        llong ans = (llong)i*(qr[j].y-1-k)-sgt.query(1,1,ny,k+1,qr[j].y-1,mx[qr[j].y]).second; //Note here!
                        fans[qr[j].id] += ans;
                    }
                    j++;
                }
            }
            q = 0; sgt.clear(1,1,ny); for(int i=1; i<=ny; i++) mx[i] = 0ll;
        }
    }
     
    Query a[N+3],b[N+3];
    int nx,ny,m,q;
     
    int main()
    {
    	int T; scanf("%d",&T);
    	while(T--)
    	{
    	    scanf("%d%d%d%d",&nx,&ny,&m,&q);
    	    for(int i=1; i<=m; i++) scanf("%d%d",&a[i].x,&a[i].y);
    	    for(int i=1; i<=q; i++) scanf("%d%d",&b[i].x,&b[i].y);
    	    //1
    	    Solve::nx = nx; Solve::ny = ny;
    	    for(int i=1; i<=m; i++) Solve::addquery(a[i].x,a[i].y,0);
    	    for(int i=1; i<=q; i++) Solve::addquery(b[i].x,b[i].y,i);
    	    Solve::solve();
    	    //2
    	    Solve::nx = ny; Solve::ny = nx;
    	    for(int i=1; i<=m; i++) Solve::addquery(a[i].y,nx+1-a[i].x,0);
    	    for(int i=1; i<=q; i++) Solve::addquery(b[i].y,nx+1-b[i].x,i);
    	    Solve::solve();
    	    //3
    	    Solve::nx = nx; Solve::ny = ny;
    	    for(int i=1; i<=m; i++) Solve::addquery(nx+1-a[i].x,ny+1-a[i].y,0);
    	    for(int i=1; i<=q; i++) Solve::addquery(nx+1-b[i].x,ny+1-b[i].y,i);
    	    Solve::solve();
    	    //4
    	    Solve::nx = ny; Solve::ny = nx;
    	    for(int i=1; i<=m; i++) Solve::addquery(ny+1-a[i].y,a[i].x,0);
    	    for(int i=1; i<=q; i++) Solve::addquery(ny+1-b[i].y,b[i].x,i);
    	    Solve::solve();
    	    for(int i=1; i<=q; i++) printf("%lld
    ",fans[i]+1);
    	    memset(fans,0,sizeof(fans));
    	}
        return 0;
    }
    
  • 相关阅读:
    Tomcat7修改根路径应用
    Linux 双网卡绑定
    nginx 动态黑名单
    LINUX 字体查看 字体更改mkfontdir
    iptables 有关计算机名解析问题
    godaddy SSL证书不信任
    要远程登录,你需要具有通过远程桌面服务进行登录的权限...
    如何用jQuery获得select的值
    jQuery 选中tr下面的第某个td
    c#中char、string转换为十六进制byte的浅析
  • 原文地址:https://www.cnblogs.com/suncongbo/p/11308252.html
Copyright © 2011-2022 走看看