Rikka with Cake(線段樹+線段樹)

ikka's birthday is on June 12th. The story of this problem happens on that day.

Today is Rikka's birthday. Yuta prepares a big cake for her: the shape of this cake is a rectangular of nn centimeters times mm centimeters. With the guidance of a grimoire, Rikka is going to cut the cake.

For simplicity, Rikka firstly builds a Cartesian coordinate system on the cake: the coordinate of the left bottom corner is (0,0)(0,0) while that of the right top corner is (n,m)(n,m). There are KK instructions on the grimoire: The iith cut is a ray starting from (xi,yi)(xi,yi) while the direction is DiDi. There are four possible directions: L, passes (xi−1,yi)(xi−1,yi); R, passes (xi+1,yi)(xi+1,yi); U, passes (xi,yi+1)(xi,yi+1); D, passes (xi,yi−1)(xi,yi−1).

Take advantage of the infinite power of Tyrant's Eye, Rikka finishes all the instructions quickly. Now she wants to count the number of pieces of the cake. However, since a huge number of cuts have been done, the number of pieces can be very large. Therefore, Rikka wants you to finish this task.

Input

The first line of the input contains a single integer T(1≤T≤100)T(1≤T≤100), the number of the test cases.

For each test case, the first line contains three positive integers n,m,K(1≤n,m≤109,1≤K≤105)n,m,K(1≤n,m≤109,1≤K≤105), which represents the shape of the cake and the number of instructions on the grimoire.

Then KK lines follow, the iith line contains two integers xi,yi(1≤xi<n,1≤yi<m)xi,yi(1≤xi<n,1≤yi<m) and a char Di∈{Di∈{'L','R','U','D'}}, which describes the iith cut.

The input guarantees that there are no more than 55 test cases with K>1000K>1000, and no two cuts share the same xx coordinate or yy coordinate, i.e., ∀1≤i<j≤K∀1≤i<j≤K, xi≠xjxi≠xj and yi≠yjyi≠yj.

Output

For each test case, output a single line with a single integer, the number of pieces of the cake.

Hint


The left image and the right image show the results of the first and the second test case in the sample input respectively. Clearly, the answer to the first test case is 33 while the second one is 55.

 

Sample Input

2
4 4 3
1 1 U
2 2 L
3 3 L
5 5 4
1 2 R
3 1 U
4 3 L
2 4 D

Sample Output

3
5

題意

從一個點開始往一個方向切蛋糕,問切完k次後,切了多少塊蛋糕。

思路

容易得出,蛋糕塊數爲交點數加一。可以通過建兩次線段樹(一次求方向向下的交點數,一次求方向向上的交點數)求解。

介紹一下方向向上的交點數得方法。

先離散化座標,按縱座標從大到小更新區間,計算交點數。說的不太明白,講一下過程,以樣例一爲例。

圖中有三個點(1,1)、(2,2)、(3,3),方向水平得更新區間長度,這樣每個點就是佔單位一得長度

(3,3)點是方向向左的 那麼【1,3】區間內的點值都+1,即sum【1】=1,sum[2]=1,sum[3]=1。

(2,2)點是方向向左的,那麼[1,2]區間的點的值都+1,這時候sum[1]=2,sum[2]=2,sum[3]=1

(1,1)點是方向向上的,這時候就計算交點個數,看sum[1]等於幾就是這一條向上的線與前面那兩條的交點個數,注意sum數組的下標都是橫座標。

方向向下的交點數就是將縱座標從小到大更新區間,計算出總交點數加一就是答案。

代碼

#include<bits/stdc++.h>
#define ll long long
#define N  400010
using namespace std;
int Sum[N],add[N];
vector<int>v[4][N];
struct node{
    int x,y;
    int id;
}eg[N];
void Clear(int n){
    for(int i=0;i<4;i++)
        for(int j=0;j<=n;j++)
            v[i][j].clear();
    memset(Sum,0,sizeof(Sum));
    memset(add,0,sizeof(add));
}
int change(char c){
    if(c=='U')return 0;
    if(c=='R')return 1;
    if(c=='D')return 2;
    if(c=='L')return 3;
}
void pushup(int o){
    Sum[o]=Sum[o<<1]+Sum[o<<1|1];
}
void pushdown(int o,int len){
    if(add[o]){
        add[o<<1]+=add[o];
        add[o<<1|1]+=add[o];
        Sum[o<<1]+=add[o]*(len-(len>>1));
        Sum[o<<1|1]+=add[o]*(len>>1);
        add[o]=0;
    }
}
void update(int x,int y,int l,int r,int o,int c){
    if(l>=x&&r<=y){
        Sum[o]+=(r-l+1)*c;
        add[o]+=c;
        return;
    }
    pushdown(o,r-l+1);
    int mid=(l+r)>>1;
    if(x<=mid)update(x,y,l,mid,o<<1,c);
    if(y>mid)update(x,y,mid+1,r,o<<1|1,c);
    pushup(o);
}
int query(int x,int l,int r,int o){
    if(l==x&&r==x){
        return Sum[o];
    }
    pushdown(o,r-l+1);
    int mid=(l+r)>>1;
    if(x<=mid)return query(x,l,mid,o<<1);
    else return query(x,mid+1,r,o<<1|1);
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        map<int,int>c,r;
        for(int i=1;i<=k;i++){
            char str[2];
            scanf("%d%d%s",&eg[i].x,&eg[i].y,str);
            eg[i].id=change(str[0]);
            c[eg[i].x]=r[eg[i].y]=1;
        }
        int h=0,w=0;
        for(auto it=c.begin();it!=c.end();it++)it->second=++h;
        for(auto it=r.begin();it!=r.end();it++)it->second=++w;
        for(int i=1;i<=k;i++){//離散化
            eg[i].x=c[eg[i].x];eg[i].y=r[eg[i].y];
            v[eg[i].id][eg[i].y].push_back(eg[i].x);
        }
        ll cnt=0;
        for(int i=1;i<=h;i++){ //按縱座標,從下往上掃,找向下的線段
            int len=v[1][i].size();
            for(int j=0;j<len;j++)update(v[1][i][j],w,1,w,1,1);
            len=v[3][i].size();
            for(int j=0;j<len;j++)update(1,v[3][i][j],1,w,1,1);
            len=v[2][i].size();
            for(int j=0;j<len;j++)cnt+=query(v[2][i][j],1,w,1);
            
        }
       memset(Sum,0,sizeof(Sum));
        memset(add,0,sizeof(add));
        for(int i=h;i>=1;i--){ //按縱座標,從上往下掃,找向上的線段
            int len=v[1][i].size();
            for(int j=0;j<len;j++)update(v[1][i][j],w,1,w,1,1);
            len=v[3][i].size();
            for(int j=0;j<len;j++)update(1,v[3][i][j],1,w,1,1);
            len=v[0][i].size();
            for(int j=0;j<len;j++)cnt+=query(v[0][i][j],1,w,1);
        }
        printf("%lld\n",cnt+1);
        Clear(h);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章