「hdu6681」Rikka with Cake【线段树】

Rikka with Cake

Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 298 Accepted Submission(s): 109

Problem Description

Rikka’s birthday is on June 12 − t h 12-th 12th. The story of this problem happens on that day.

Today is R i k k a ′ s Rikka's Rikkas birthday. Yuta prepares a big cake for her: the shape of this cake is a rectangular of n centimeters times m centimeters. With the guidance of a grimoire, R i k k a Rikka Rikka is going to cut the cake.

For simplicity, R i k k a Rikka Rikka firstly builds a Cartesian coordinate system on the cake: the coordinate of the left bottom corner is ( 0 , 0 ) (0,0) (0,0) while that of the right top corner is ( n , m ) (n,m) (n,m). There are K K K instructions on the grimoire: The i − t h i-th ith cut is a ray starting from ( x i , y i ) (x_i,y_i) (xi,yi) while the direction is D i D_i Di. There are four possible directions: L L L, passes ( x i − 1 , y i ) (x_{i−1},y_i) (xi1,yi); R, passes ( x i + 1 , y i ) (x_{i+1},y_i) (xi+1,yi); U, passes ( x i , y i + 1 ) (x_i,y_{i+1}) (xi,yi+1); D, passes ( x i , y i − 1 ) (x_i,y_{i−1}) (xi,yi1).

Take advantage of the infinite power of T y r a n t ′ s Tyrant's Tyrants Eye, R i k k a Rikka 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, R i k k a Rikka Rikka wants you to finish this task.

Input

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

For each test case, the first line contains three positive integers n , m , K ( 1 ≤ n , m ≤ 1 0 9 , 1 ≤ K ≤ 1 0 5 ) n,m,K(1\leq n,m\leq 10^9,1\leq K\leq 10^5) n,m,K(1n,m109,1K105), which represents the shape of the cake and the number of instructions on the grimoire.

Then K K K lines follow, the ith line contains two integers x i , y i ( 1 ≤ x i &lt; n , 1 ≤ y i &lt; m ) x_i,y_i(1\leq x_i&lt;n,1\leq y_i&lt;m) xi,yi(1xi<n,1yi<m) and a char D i ∈ { ′ L ′ , ′ R ′ , ′ U ′ , ′ D ′ } D_i∈\{&#x27;L&#x27;,&#x27;R&#x27;,&#x27;U&#x27;,&#x27;D&#x27;\} Di{L,R,U,D}, which describes the ith cut.

The input guarantees that there are no more than 5 test cases with K &gt; 1000 K&gt;1000 K>1000, and no two cuts share the same x x x coordinate or y y y coordinate, i . e . , ∀ 1 ≤ i &lt; j ≤ K , x i   ! = x j a n d   y i   ! =   y j . i.e., \forall1\leq i&lt;j\leq K, x_i\ != x_j and\ y_i\ !=\ y_j. i.e.,1i<jK,xi !=xjand yi != 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 3 3 3 while the second one is 5 5 5.

在这里插入图片描述

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

Source

2019 Multi-University Training Contest 9

题意

  • 就是给你一个 n × m n\times m n×m的蛋糕,每次从蛋糕中间一个地方向四个方向中的一个方向切一刀【切的方向平行于其中一个蛋糕边缘】,问最后共几块蛋糕,没有切断的算一块

题解

  • 比赛的时候一眼看出了答案是交点个数 + 1 +1 +1,和队友说了一下队友同意了,然后我这个伪几何选手直接套了一个线段交点个数的板子,这个板子是直接从网上搬过来的,表面看上去复杂度是 n log ⁡ n n\log n nlogn,但是交上去 T T T掉了,然后还是老老实实写线段树吧:(
  • 先考虑向上切的与其他横切的交点个数,从上至下遍历所有横切的,在线段树中区间加值,然后对于一个向上切,单点查询值就是交点个数了,向下切在从下至上遍历一次就行了

代码

#pragma GCC optimize ("O3")
#include<bits/stdc++.h>

using namespace std;
const int maxn=2e5+10;

namespace IO{ 
    #define BUF_SIZE 100000 
    #define OUT_SIZE 100000 

    bool IOerror=0; 
    inline char nc(){ 
        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; 
        if (p1==pend){ 
            p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); 
            if (pend==p1){IOerror=1;return -1;} 
        } 
        return *p1++; 
    } 
    inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} 
    inline bool read(double &x){ 
        bool sign=0; char ch=nc(); x=0; 
        for (;blank(ch);ch=nc()); 
        if (IOerror) return false; 
        if (ch=='-')sign=1,ch=nc(); 
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 
        if (ch=='.'){ 
            double tmp=1; ch=nc(); 
            for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0'); 
        } 
        if (sign)x=-x; return true;
    } 
    template<typename T>
    inline bool read(T &x){ 
        bool sign=0; char ch=nc(); x=0; 
        for (;blank(ch);ch=nc()); 
        if (IOerror) return false; 
        if (ch=='-')sign=1,ch=nc(); 
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 
        if (sign)x=-x; return true;
    } 
    inline bool read(char *s){ 
        char ch=nc(); 
        for (;blank(ch);ch=nc()); 
        if (IOerror) return false; 
        for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch; 
        *s=0; return true;
    } 
};
using namespace IO;

int sum[maxn<<2],mark[maxn<<2];

void down(int id)
{
    mark[id<<1]+=mark[id];mark[id<<1|1]+=mark[id];
    mark[id]=0;
}

void build(int id,int l,int r)
{
    mark[id]=0;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(id<<1,l,mid);build(id<<1|1,mid+1,r);
}

void update(int id,int L,int R,int l,int r,long long add)
{
    if(l<=L&&R<=r) {
        mark[id]+=add;
        return;
    }
    if(mark[id]!=0) down(id);int mid=(L+R)>>1;
    if(l<=mid) update(id<<1,L,mid,l,r,add);
    if(r>mid) update(id<<1|1,mid+1,R,l,r,add);
}

int query(int id,int L,int R,int pos)
{
    if(L==R) return mark[id];
    int mid=(L+R)>>1;
    if(mark[id]) down(id);
    if(pos<=mid) return query(id<<1,L,mid,pos);
    else return query(id<<1|1,mid+1,R,pos);
}

struct line{
    int x,y,dir;
    line(int a=0,int b=0,int d=0) {
        x=a;y=b;dir=d;
    }
}a[maxn];

char s[10];
int b[maxn],c[maxn],w,h,n,m,k;
vector<int> vec[4][maxn];

void clear_()
{
    for(int i=0;i<=3;i++) for(int j=0;j<=h;j++) vec[i][j].clear();
}

int main()
{
    int t;read(t);
    while(t--) {
        read(n);read(m);read(k);
        for(int i=1,x,y;i<=k;i++) {
            read(a[i].x);read(a[i].y);read(s+1);
            b[i]=a[i].x;c[i]=a[i].y;
            if(s[1]=='L') a[i].dir=3;
            else if(s[1]=='R') a[i].dir=1;
            else if(s[1]=='U') a[i].dir=0;
            else a[i].dir=2;
        }
        sort(b+1,b+k+1);
        sort(c+1,c+k+1);

        w=unique(b+1,b+k+1)-b-1;
        h=unique(c+1,c+k+1)-c-1;
        for(int i=1;i<=k;i++) {
            a[i].x=lower_bound(b+1,b+k+1,a[i].x)-b;
            a[i].y=lower_bound(c+1,c+k+1,a[i].y)-c;
            vec[a[i].dir][a[i].y].push_back(a[i].x);

        }
        
        build(1,1,w);
        long long ans=0;
        for(int i=1;i<=h;i++) {
            for(auto j:vec[1][i]) update(1,1,w,j,w,1);
            for(auto j:vec[3][i]) update(1,1,w,1,j,1);

            for(auto j:vec[2][i]) ans+=query(1,1,w,j);
        }
        build(1,1,w);
        for(int i=h;i>=1;i--) {
            for(auto j:vec[1][i]) update(1,1,w,j,w,1);
            for(auto j:vec[3][i]) update(1,1,w,1,j,1);
            for(auto j:vec[0][i]) ans+=query(1,1,w,j);
        }
        printf("%lld\n",ans+1);

        clear_();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值