ACM暑假训练日记 17.8.23 多维改段求点型树状数组
来源:互联网 发布:华艺服装淘宝店 编辑:程序博客网 时间:2024/05/29 17:29
今天继续做了一下树状数组的专题,上午做了一个树状数组+二分的题目比较简单的二分,用树状数组求和进行判断,二分得到最后结果。
下午在专题里面找到俩水题,轻松A掉,虽然是水题,但是比较有代表性,是两个多维改段求点型树状数组问题
首先是一个二维的
点击打开原题链接
题意,输入n,m,一个初始为0的nxn矩阵
接着m个操作
有两种情况 C a,b,c,d
将(a,b)到(c,d)范围内的矩阵进行 0 1 翻转(若原1则0,若0,则1)
仿照一维树状数组,关键点是在改变数值的那里,SUM(a,b)后,我们要消除不在要处理矩阵外的改变,本题另一个简单之处在于数值只能是0 1,而且矩形数量不大,我们只需要每次改变都加1,之后对2取余即可,用int就能实现。要消除不必要的改变的方法就是将不应该改变的部分改变偶数次,这样的话还是原值,可看做未改变,画画图就很清楚该怎么进行清除了。对于一般的题目,当不应该改变的地方加了多少,相应的,我们就应该加去多少,以确保数值不变
只需要记住一点,对于不应改变的地方,多改变了多少,就要清除多少
AC代码:
#include<stdio.h>
#include<string.h>
#define MAX 1005
int t,n,m,x1,x2,y1,y2;
long long e[MAX][MAX];
char op;
int lowbit(int k)
{
return k&(-k);
}
int SUM(int x,int y)
{
int re=0;
int yy=y;
while(x)
{
y=yy;
while(y)
{
re+=e[x][y];
y-=lowbit(y);
}
x-=lowbit(x);
}
return re;
}
void ADD(int x,int y)
{
int yy=y;
while(x<=n+1)
{
y=yy;
while(y<=n+1)
{
e[x][y]++;
y+=lowbit(y);
}
x+=lowbit(x);
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
memset(e,0,sizeof(e));
scanf("%d%d",&n,&m);
while(m--)
{
getchar();
scanf("%c",&op);
if(op=='C')
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1++;x2++;y1++;y2++;
**********************************
ADD(x2,y2);
ADD(x2,y1-1);
ADD(x1-1,y2);
ADD(x1-1,y1-1);
**********************************
}
else
{
scanf("%d%d",&x1,&y1);
printf("%d\n",(SUM(x1,y1))%2);
}
}
if(t)printf("\n");
}
}
再一个是三维的,换换说法罢了,基本是同一个代码过
点击打开链接
题意:
类似于上面,换为三维矩阵,输入时略有不同,不多叙述。
思路同上,注意消除的地方,不过和二维很类似
AC代码:
#include<stdio.h>
#include<string.h>
using namespace std;
#define MAX 105
int e[MAX][MAX][MAX],n,m,x1,x2,y1,y2,z1,z2,op;
int lowbit(int k)
{
return k&(-k);
}
int SUM(int x,int y,int z)
{
int yy=y;
int zz=z;
int re=0;
while(x)
{
y=yy;
while(y)
{
z=zz;
while(z)
{
re+=e[x][y][z];
z-=lowbit(z);
}
y-=lowbit(y);
}
x-=lowbit(x);
}
return re;
}
void ADD(int x,int y,int z)
{
int yy=y;
int zz=z;
while(x<=n+1)
{
y=yy;
while(y<=n+1)
{
z=zz;
while(z<=n+1)
{
e[x][y][z]++;
z+=lowbit(z);
}
y+=lowbit(y);
}
x+=lowbit(x);
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(e,0,sizeof(e));
while(m--)
{
scanf("%d",&op);
if(op)
{
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
************************************
ADD(x2+1,y2+1,z2+1);
ADD(x1,y2+1,z2+1);
ADD(x2+1,y1,z2+1);
ADD(x2+1,y2+1,z1);
ADD(x2+1,y1,z1);
ADD(x1,y2+1,z1);
ADD(x1,y1,z2+1);
ADD(x1,y1,z1);
************************************
}
else
{
scanf("%d%d%d",&x1,&y1,&z1);
printf("%d\n",(SUM(x1,y1,z1)%2));
}
}
}
}
对比两段代码编辑的部分,规律显而易见,类似于一种全排列,虽然是俩水题,但价值还是有的,对以后处理这方面的问题很有帮助
今天收获还是不错的
- ACM暑假训练日记 17.8.23 多维改段求点型树状数组
- ACM暑假训练日记 17.8.17 树状数组
- ACM暑假集训日记 17.8.15 树状数组
- ACM暑假集训日记 17.8.16 树状数组
- ACM暑假集训日记 17.8.18 树状数组
- ACM暑假训练日记 17.8.12
- ACM暑假训练日记 17.8.19
- ACM暑假训练日记 17.8.21
- ACM暑假训练日记 17.8.22
- ACM暑假训练 问题 G: Balanced Photo (树状数组优化)
- 暑假集训日记--8.19--树状数组
- 暑假集训日记--8.21--树状数组
- 暑假集训日记--8.23--树状数组
- 2017暑假训练之树状数组
- ACM暑假训练第3场中石油集训题(记忆化搜索,dp,树状数组)
- 暑假集训日记--8.16--练习赛题+树状数组
- 暑假集训日记--8.17--树状数组+练习赛
- 暑假集训日记--8.22--树状数组+练习赛
- C语言实现一个列表式的学生信息管理系统(完善)
- ccf 201612-2 工资计算
- glibc源码分析之用户管理
- 备战国赛--散乱插值及MATLAB绘图函数
- PHP正则匹配与替换的简单例子
- ACM暑假训练日记 17.8.23 多维改段求点型树状数组
- JVM_Java垃圾处理机制
- UI 一一 UI基础知识
- js九九乘法表
- 设计模式(补充)
- Mac 下MySQL的安装与修改密码
- 1806: [Ioi2007]Miners 矿工配餐
- 为什么要重写hashcode()方法以及如何重写hashcode和equals方法
- hdu 4638 Group