题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6681
题意:给定一个n*m的蛋糕,再给出K个操作,每次都是从蛋糕的中间向四个方向中的一个切过去,问最后蛋糕被切成多少块。
数据范围:1≤T≤100,1≤n,m≤109,1≤K≤105,1≤xi
思路:我们发现切的蛋糕块数正好等于交点的个数+1,那么这道题就转换成求交点个数的题了,首先离散化,然后给定的向上和向右的操作按照x递增排序,开始对y边插入(先插入比向上的x小的)边访问建立树状数组。其余四种情况相同的方法处理就好(向下和向右,向上和向左,向下和向左)。
#include
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,m,t,k,tot=0;
int xx[N],yy[N];
struct p{
int x,y,qx,qy;
}a1[N],a2[N],a3[N],a4[N];
struct BIT{
ll tree[N];
void init(int k){
for(int i=1;i<=k;i++)tree[i]=0;
}
void update(int x,ll val){
while(x<=k){
tree[x]+=val;
x+=x&-x;
}
}
ll getsum(int x){
ll ans=0;
while(x){
ans+=tree[x];
x-=x&-x;
}
return ans;
}
}bit[5];
bool cmp1(p aa,p bb){
return aa.xbb.x;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=4;i++)bit[i].init(k+5);
int x,y;
char s[5];
int cnt1=0,cnt2=0,cnt3=0,cnt4=0;
for(int i=1;i<=k;i++){
scanf("%d%d%s",&x,&y,s);
if(s[0]=='U')a1[++cnt1].x=x,a1[cnt1].y=y;
else if(s[0]=='L')a2[++cnt2].x=x,a2[cnt2].y=y;
else if(s[0]=='R')a3[++cnt3].x=x,a3[cnt3].y=y;
else if(s[0]=='D')a4[++cnt4].x=x,a4[cnt4].y=y;
xx[i]=x,yy[i]=y;
}
sort(xx+1,xx+k+1);
sort(yy+1,yy+k+1);
for(int i=1;i<=cnt1;i++){
a1[i].qx=lower_bound(xx+1,xx+k+1,a1[i].x)-xx;
a1[i].qy=lower_bound(yy+1,yy+k+1,a1[i].y)-yy;
}
for(int i=1;i<=cnt2;i++){
a2[i].qx=lower_bound(xx+1,xx+k+1,a2[i].x)-xx;
a2[i].qy=lower_bound(yy+1,yy+k+1,a2[i].y)-yy;
}
for(int i=1;i<=cnt3;i++){
a3[i].qx=lower_bound(xx+1,xx+k+1,a3[i].x)-xx;
a3[i].qy=lower_bound(yy+1,yy+k+1,a3[i].y)-yy;
}
for(int i=1;i<=cnt4;i++){
a4[i].qx=lower_bound(xx+1,xx+k+1,a4[i].x)-xx;
a4[i].qy=lower_bound(yy+1,yy+k+1,a4[i].y)-yy;
}
sort(a1+1,a1+cnt1+1,cmp1);
sort(a3+1,a3+cnt3+1,cmp1);
sort(a4+1,a4+cnt4+1,cmp1);
int ji=1;
ll ans=0;
for(int i=1;i<=cnt1;i++){
for(int j=ji;j<=cnt3;j++){
if(a3[j].qx<=a1[i].qx){
bit[1].update(k+1-a3[j].qy,1);
ji=j+1;
}
else break;
}
ans+=bit[1].getsum(k+1-a1[i].qy);
}
ji=1;
for(int i=1;i<=cnt4;i++){
for(int j=ji;j<=cnt3;j++){
if(a3[j].qx<=a4[i].qx){
bit[2].update(a3[j].qy,1);
ji=j+1;
}
else break;
}
ans+=bit[2].getsum(a4[i].qy);
}
sort(a1+1,a1+cnt1+1,cmp2);
sort(a2+1,a2+cnt2+1,cmp2);
sort(a4+1,a4+cnt4+1,cmp2);
ji=1;
for(int i=1;i<=cnt1;i++){
for(int j=ji;j<=cnt2;j++){
if(a2[j].qx>=a1[i].qx){
bit[3].update(k+1-a2[j].qy,1);
ji=j+1;
}
else break;
}
ans+=bit[3].getsum(k+1-a1[i].qy);
}
ji=1;
for(int i=1;i<=cnt4;i++){
for(int j=ji;j<=cnt2;j++){
if(a2[j].qx>=a4[i].qx){
bit[4].update(a2[j].qy,1);
ji=j+1;
}
else break;
}
ans+=bit[4].getsum(a4[i].qy);
}
printf("%lld\n",ans+1);
}
return 0;
}