zoukankan      html  css  js  c++  java
  • ICPC 2015 Shenyang Online-E-EXCITED DATAbase

    题目描述

    She says that any Pavarotti among the nightingales will serenade his mate while she sits on her eggs. She says that any excited database can answer the queries efficiently.
    You are given the two dimensional database as a matrix A with n rows and n columns. In the beginning, A[i][j] = 0 for all 1 ≤ i, j ≤ n. Then q operations or queries will be given in turn.
    You should maintain the database for two type of operations:
    • 1 L R: for each element A[i][j] which satisfy L ≤ i + j ≤ R, increase the value to A[i][j] + 1, where 2 ≤ L ≤ R ≤ 2n.
    • 2 L R: for each element A[i][j] which satisfy L ≤ i − j ≤ R, increase the value to A[i][j] + 1, where 1 − n ≤ L ≤ R ≤ n − 1.
    Meanwhile, you should answer the queries:
    • 3 x1 x2 y1 y2 : count the value of elements A[i][j] which satisfy x1 ≤ i ≤ x  and y1 ≤ j ≤ y2 , where 1 ≤ x1 < x2 ≤ n and 1 ≤ y1 < y2 ≤ n.

    输入

    The input contains several test cases. The first line of the input is a single integer t which is the number of test cases. Then t test cases follow.
    Each test case contains several lines. The first line contains the integer n and q. The i-th line of the next q lines contains an operation “1 L R” or “2 L R”, or a query “3 x1 x2 y1 y2 ”.
    The sum of n for all test cases would not be larger than 200000 and the sum of q would not be larger than 50000.

    输出

    For each test case, you should output answers to queries printed one per line.

    样例输入

    2
    6 6
    2 0 1
    3 1 4 3 5
    3 2 5 2 3
    1 5 7
    3 1 4 3 5
    3 2 5 2 3
    6 26
    2 -4 -1
    3 1 4 2 5
    3 3 6 4 6
    1 4 7
    3 2 5 2 3
    3 1 4 2 5
    2 -3 -1
    3 1 4 3 5
    1 3 5
    1 2 3
    3 2 5 2 3
    3 1 4 2 5
    3 3 6 4 6
    2 0 4
    3 1 4 3 5
    3 1 4 2 5
    1 9 11
    2 1 2
    3 2 5 2 3
    3 3 6 4 6
    2 -2 2
    1 7 12
    3 1 4 3 5
    3 2 5 2 3
    3 1 4 2 5
    3 3 6 4 6
    

    样例输出

    Case #1:
    3
    4
    11
    10
    Case #2:
    10
    6
    8
    22
    26
    12
    38
    13
    32
    44
    23
    30
    49
    33
    67
    53

    题意就是给你一个n×n的矩阵,有三种操作
    1LR 给L<=i+j<=R的点加1
    2LR 给L<=i- j<=R的点加1
    3 x1 x2 y1 y2 询问x1<=i<=x2,y1<=j<=y2的点的和

    建两棵线段树,一棵维护对角线(i-j相同的一斜列,不妨称i-j的值为斜率),一棵维护负对角线(i+j相同)
    对每棵线段树维护sum:sum(l,r)为斜率在l和r之间的数的和
    sumL:sumL(l,r)为斜率在l和r之间,l行取1个,l+1行取两个……所形成的三角形,即一个等差数列的和
    sumR:sumR(l,r)为斜率在l和r之间,r行取1个,r-1行取两个……所形成的三角形,即一个等差数列的和

    对每次询问,为一个矩形,拆成两个等腰直角三角形和一个平行四边形的和,对角线和负对角线单独计算
    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=4e5+10;
    struct tree{
        int l,r;
        ll sum,sumL,sumR,lazy;
        int length() {return r-l+1;}
        int maintain(ll a)
        {
            lazy+=a;
            sum+=a*length();
            ll add=a*length()*(length()+1)/2;
            sumL+=add;
            sumR+=add;
        }
    }t[2][N*4];
    int n,q,op,T;
    void Pushup(int s,int id)
    {
        t[id][s].sum=t[id][s<<1].sum+t[id][s<<1|1].sum;
        t[id][s].sumL=t[id][s<<1].sumL+t[id][s<<1|1].sumL+t[id][s<<1|1].sum*(t[id][s<<1].length());
        t[id][s].sumR=t[id][s<<1].sumR+t[id][s<<1|1].sumR+t[id][s<<1].sum*(t[id][s<<1|1].length());
    }
    void Pushdown(int s,int id)
    {
        if (t[id][s].lazy)
        {
            t[id][s<<1].maintain(t[id][s].lazy);
            t[id][s<<1|1].maintain(t[id][s].lazy);
            t[id][s].lazy=0;
        }
    }
    void build(int s,int l,int r,int id)
    {
        t[id][s].l=l; t[id][s].r=r;
        t[id][s].sum=t[id][s].sumL=t[id][s].sumR=t[id][s].lazy=0;
        if (l==r) return ;
        int mid=(t[id][s].l+t[id][s].r)>>1;
        build(s<<1,l,mid,id);
        build(s<<1|1,mid+1,r,id);
        Pushup(s,id);
    }
    void update(int s,int L,int R,int id)
    {
        int l=t[id][s].l,r=t[id][s].r;
        if (L<=l&&r<=R)
        {
            t[id][s].maintain(1);
            return ;
        }
        Pushdown(s,id);
        int mid=(l+r)>>1;
        if (L<=mid) update(s<<1,L,R,id);
        if (R>mid) update(s<<1|1,L,R,id);
        Pushup(s,id);
    }
    ll query(int s,int L,int R,int id)
    {
        int l=t[id][s].l,r=t[id][s].r;
        if (L<=l&&r<=R) return t[id][s].sum;
        Pushdown(s,id);
        int mid=(l+r)>>1;
        ll ret=0;
        if (L<=mid) ret+=query(s<<1,L,R,id);
        if (R>mid) ret+=query(s<<1|1,L,R,id);
        Pushup(s,id);
        return ret;
    }
    ll queryL(int s,int L,int R,int id)
    {
        int l=t[id][s].l,r=t[id][s].r;
        if (L<=l&&r<=R) return t[id][s].sumL+t[id][s].sum*(l-L);
        Pushdown(s,id);
        int mid=(l+r)>>1;
        ll ret=0;
        if (L<=mid) ret+=queryL(s<<1,L,R,id);
        if (R>mid) ret+=queryL(s<<1|1,L,R,id);
        Pushup(s,id);
        return ret;
    }
    ll queryR(int s,int L,int R,int id)
    {
        int l=t[id][s].l,r=t[id][s].r;
        if (L<=l&&r<=R) return t[id][s].sumR+t[id][s].sum*(R-r);
        Pushdown(s,id);
        int mid=(l+r)>>1;
        ll ret=0;
        if (L<=mid) ret+=queryR(s<<1,L,R,id);
        if (R>mid) ret+=queryR(s<<1|1,L,R,id);
        Pushup(s,id);
        return ret;
    }
     
    int main()
    {
        scanf("%d",&T);
        for (int ca=1;ca<=T;ca++)
        {
            printf("Case #%d:
    ",ca);
            int l,r;
            int X1,X2,Y1,Y2;
            scanf("%d%d",&n,&q);
            build(1,2,n*2,0);
            build(1,1,2*n-1,1);
            while (q--)
            {
                scanf("%d",&op);
                if (op==1)
                {
                    scanf("%d%d",&l,&r);
                    update(1,l,r,0);
                }
                else if (op==2)
                {
                    scanf("%d%d",&l,&r);
                    update(1,l+n,r+n,1);
                }
                else
                {
                    scanf("%d%d%d%d",&X1,&X2,&Y1,&Y2);
                    ll ans=0;
                    ll wid=min(X2-X1,Y2-Y1)+1;
     
                    l=X2+Y1;r=X1+Y2;
                    if (l>r) swap(l,r);
                    ans+=query(1,l,r,0)*wid;
                    ans+=queryL(1,X1+Y1,l-1,0);
                    ans+=queryR(1,r+1,X2+Y2,0);
     
                    l=X1-Y1+n,r=X2-Y2+n;
                    if (l>r) swap(l,r);
                    ans+=query(1,l,r,1)*wid;
                    ans+=queryL(1,X1-Y2+n,l-1,1);
                    ans+=queryR(1,r+1,X2-Y1+n,1);
                    printf("%lld
    ",ans);
                }
            }
        }
        return 0;
    }
    一个WA了无数发最终参考大佬博客才写成的代码
  • 相关阅读:
    我的访问量咋才3万了
    Khronos发布WebGL标准规范 1.0
    X3Dom V1.2发布
    解决Linux(Fedora Ubuntu)笔记本的待机休眠
    多用户虚拟Web3D环境Deep MatrixIP9 1.04发布
    网络科技公司Web开发团队管理的小结
    XamlReader 动态加载XAML
    Excel Data Reader开源的.NET excel读取库
    .net Sql server 事务的两种用法
    通过使用客户端证书调用 Web 服务进行身份验证{转}
  • 原文地址:https://www.cnblogs.com/tetew/p/9734186.html
Copyright © 2011-2022 走看看