教室中的座位
Time Limit:10000MS Memory Limit:65536K
Total Submit:78 Accepted:7
Description
教室中座位的数目有多有少,并不总是相同。每到考试的时候就会出现有些教室有多余的座位的情况,因为考试期间这些多余的座位也不能让别人使用。这实在是一种浪费。要是这些座位能够自由移动该多好啊!虽然现实中,这个想法无法实现,可是不妨碍我们在这里臆想一下!
为了简化问题,我们假设所有的教室在同一层楼上。假设这一层楼被分成了一个个方格(行数和列数都不超过1000),每个方格是一间教室。开始时,每间教室都有1个座位。然后,我们可以对这些教室的座位进行处理:给某间教室添加座位,从某间教室搬走座位,从一间教室向另一间教室转移座位,查看某间教室的座位数。
Input
输入的第一行是测试用例个数T (1 ≤ T ≤ 10)。
对于每个测试用例,第一行是整数Q (1 < Q < 100,000), 后面紧跟 Q 行,每行是一个处理操作。共有4种操作: A x y m 表示给位于(x, y)的教室添加m个座位; D x y m 表示从位于(x, y)的教室搬走m个座位,如果该教室的座位数不足,则搬走其所有座位; M x1 y1 x2 y2 m表示从位于(x1, y1)的教室向位于(x2, y2)的教室转移m个座位,如果位于(x1, y1)的教室中的座位数不足m个,则搬走其所有座位;S x1 y1 x2 y2表示查询以(x1, y1) 与(x2, y2)这两个点确定的矩形范围内的教室中的座位总数目。 0 ≤ x1, y1, x2, y2, x, y < 1000,0 ≤ m < 100.
Output
对于每个测试用例, 输出 "Case X:" X是测试用例的序号.
对于每个查询操作输出查询结果。
Sample Input
2
3
S 1 1 2 2
A 1 1 3
S 1 1 1 1
4
S 1 1 1 1
D 1 1 2
S 1 1 1 2
M 1 1 2 2 100
Sample Output
Case 1:
4
4
Case 2:
1
1
这题花了好多时间。。。尝试了好几种方法都没能AC。。
比如一维线段树,树状数组这两种方法我反正没能AC。。可能是这两种方法掌握的不好。。所以没能找到AC的办法。。
最后查资料。。原来还有其他的线段树,可以用二维线段树的。。
最后套用某个大牛的二维线段树模版,终于AC!
下面是AC代码:
#include<iostream>
using namespace std;
# define HMax 3005
# define AMax 3005
struct sub_tree
{
int la,ra,Max;
};
struct main_tree
{
sub_tree A[AMax];
int l,r;
}H[HMax];
int num;
void sub_bulid(int l,int r,int la,int ra,int t1,int t)
{
H[t].A[t1].la=la;
H[t].A[t1].ra=ra;
H[t].A[t1].Max=(ra-la+1)*(r-l+1);
if(la==ra) return;
int mid=(la+ra)/2;
sub_bulid(l,r,la,mid,2*t1,t);
sub_bulid(l,r,mid+1,ra,2*t1+1,t);
}
void bulid(int l,int r,int la,int ra,int t)
{
H[t].l=l;
H[t].r=r;
sub_bulid(l,r,la,ra,1,t);
if(l==r) return;
int mid=(l+r)/2;
bulid(l,mid,la,ra,2*t);
bulid(mid+1,r,la,ra,2*t+1);
}
void sub_insert(int a,int L,int t1,int t)
{
if(H[t].A[t1].Max+L>=0)
{
H[t].A[t1].Max+=L;
}
else
{
H[t].A[t1].Max=0;
}
if(H[t].A[t1].la == H[t].A[t1].ra) return ;
if(a<=H[t].A[2*t1].ra) sub_insert(a,L,2*t1,t);
else sub_insert(a,L,2*t1+1,t);
}
void insert(int h,int a,int L,int t)
{
sub_insert(a,L,1,t);
if(H[t].l==H[t].r) return;
if(h<=H[2*t].r) insert(h,a,L,2*t);
else insert(h,a,L,2*t+1);
}
int sub_query(int A1,int A2,int t1,int t)
{
if(H[t].A[t1].la==A1 && H[t].A[t1].ra==A2)
return num+=H[t].A[t1].Max;
if(A2<=H[t].A[2*t1].ra) return sub_query(A1,A2,2*t1,t);
else if(A1>=H[t].A[2*t1+1].la) return sub_query(A1,A2,2*t1+1,t);
else
{
sub_query(A1,H[t].A[2*t1].ra,2*t1,t);
sub_query(H[t].A[2*t1+1].la,A2,2*t1+1,t);
}
}
void query(int h1,int h2,int A1,int A2,int t)
{
if(H[t].l==h1 && H[t].r==h2)
{
num=sub_query(A1,A2,1,t);
return;
}
if(h2<=H[2*t].r) query(h1,h2,A1,A2,2*t);
else if(h1>=H[2*t+1].l) query(h1,h2,A1,A2,2*t+1);
else
{
query(h1,H[2*t].r,A1,A2,2*t);
query(H[2*t+1].l,h2,A1,A2,2*t+1);
}
}
void solveA()
{
int x,y,m;
scanf("%d%d%d",&x,&y,&m);
insert(x,y,m,1);
}
void solveD()
{
int x,y,m,t;
scanf("%d%d%d",&x,&y,&m);
num=0;
query(x,x,y,y,1);
if(num>=m)
t=m;
else
t=num;
insert(x,y,-t,1);
}
void solveM()
{
int x1,y1,x2,y2,m,t;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&m);
num=0;
query(x1,x1,y1,y1,1);
if(num>=m)
t=m;
else
t=num;
insert(x1,y1,-t,1);
insert(x2,y2,t,1);
}
void solveS()
{
int x1,y1,x2,y2,t;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(x1>x2)
t=x1,x1=x2,x2=t;
if(y1>y2)
t=y1,y1=y2,y2=t;
num=0;
query(x1,x2,y1,y2,1);
printf("%d\n",num);
}
int main()
{
// freopen("G:\\text.txt","r",stdin);
int n,i,t,k=0;
cin>>t;
while(t--)
{
bulid(0,1000,0,1000,1);
scanf("%d",&n);
printf("Case %d:\n",++k);
for(i=0;i<n;i++)
{
getchar();
char ch=getchar();
if(ch=='A')
solveA();
if(ch=='D')
solveD();
if(ch=='M')
solveM();
if(ch=='S')
solveS();
}
}
return 0;
}