您的位置:首页 > 其它

hdu5465

2015-11-05 20:43 197 查看
这道题明显是博弈+二维线段树,但是不知道怎么写出了时间排名倒几的程序。

已ac的代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 510
#pragma comment(linker, "/STACK:1024000000,1024000000")

int ornum[N*N*10];
int allx1,ally1,allx2,ally2;
int changeto;
int cnum

;

void create(int root,int x1,int y1,int x2,int y2){
if(x1==x2&&y1==y2){
ornum[root]=cnum[x1][y1];
//printf("%d %d %d %d %d\n",x1,y1,x2,y2,ornum[root]);
}
else{
int xmiddle=(x1+x2)>>1;
int ymiddle=(y1+y2)>>1;

create((root<<2)+1,x1,y1,xmiddle,ymiddle);
if(y1!=y2){
create((root<<2)+2,x1,ymiddle+1,xmiddle,y2);
}
else{
ornum[(root<<2)+2]=0;
}

if(x1!=x2){
create((root<<2)+3,xmiddle+1,y1,x2,ymiddle);
}
else{
ornum[(root<<2)+3]=0;
}

if(x1!=x2&&y1!=y2){
create((root<<2)+4,xmiddle+1,ymiddle+1,x2,y2);
}
else{
ornum[(root<<2)+4]=0;
}

ornum[root]=ornum[(root<<2)+1]^ornum[(root<<2)+2]^ornum[(root<<2)+3]^ornum[(root<<2)+4];//ornum[(root<<2)+2]写成了ornum[(root)<<2+2],于是就一直有问题

}

return;
}

int query(int root,int x1,int y1,int x2,int y2){
if(allx1<=x1&&allx2>=x2&&ally1<=y1&&ally2>=y2){//把x,y和allx,ally之间的关系想反了,所以这里写反了,大于等于和小于等于左右两边写反了。
return ornum[root];
}
else{
int xmiddle=(x1+x2)>>1;
int ymiddle=(y1+y2)>>1;
int ans=0;

if(allx1<=xmiddle){
if(ally1<=ymiddle){
ans^=query((root<<2)+1,x1,y1,xmiddle,ymiddle);
}
if(ally2>ymiddle&&y1!=y2){
ans^=query((root<<2)+2,x1,ymiddle+1,xmiddle,y2);//这里写成了xmiddle+1,y1,所以一直栈溢出?
}
}
if(allx2>xmiddle&&x1!=x2){
if(ally1<=ymiddle){
ans^=query((root<<2)+3,xmiddle+1,y1,x2,ymiddle);
}
if(ally2>ymiddle&&y1!=y2){
ans^=query((root<<2)+4,xmiddle+1,ymiddle+1,x2,y2);
}
}

return ans;
}
}

void change(int root,int x1,int y1,int x2,int y2){
if(x1==x2&&y1==y2){
ornum[root]=changeto;
}
else{
int xmiddle=(x1+x2)>>1;
int ymiddle=(y1+y2)>>1;

if(allx1<=xmiddle&&ally1<=ymiddle){
change((root<<2)+1,x1,y1,xmiddle,ymiddle);
}
else if(allx1<=xmiddle&&ally1>ymiddle){
change((root<<2)+2,x1,ymiddle+1,xmiddle,y2);
}
else if(allx1>xmiddle&&ally1<=ymiddle){
change((root<<2)+3,xmiddle+1,y1,x2,ymiddle);
}
else{
change((root<<2)+4,xmiddle+1,ymiddle+1,x2,y2);
}

ornum[root]=ornum[(root<<2)+1]^ornum[(root<<2)+2]^ornum[(root<<2)+3]^ornum[(root<<2)+4];
}

return;
}

int main(){
int t;
int n,m,q;
int op;
//int x1,x2,y1,y2;

scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&q);

for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&cnum[i][j]);//二维线段树不像一维的,可以在建树是输入,因为二维的如果这样做,会错乱。
}
}

create(0,1,1,n,m);
//printf("wo shi da hao ren");
for(int i=0;i<q;i++){
scanf("%d",&op);
if(op==1){
scanf("%d%d%d%d",&allx1,&ally1,&allx2,&ally2);

//printf("%d %d %d %d\n",allx1,ally1,allx2,ally2);
/*printf("Yes\n");*/
//printf("%d %d\n",query(0,1,1,n,m),ornum[0]);
if(query(0,1,1,n,m)==0){//猜测:query使得栈溢出
printf("No\n");
}
else{
printf("Yes\n");
}
}
else{
scanf("%d%d%d",&allx1,&ally1,&changeto);
change(0,1,1,n,m);
}
}
}

return 0;
}

参考链接:
http://blog.csdn.net/dingding_tao/article/details/48596601
看别人的题解使用二维树状数组做的,于是就又写了一遍,结果发现我理解的二维数组只不过是很多一维数组的集合罢了

,将近超时。

将近超时的ac的代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 510

int bit

;
int cnum

;
int n,m;

int lowbit(int x){
return x&((~x)+1);
}

void change(int x,int y,int from,int changeto){
while(y<=m){
bit[x][y]^=from;
bit[x][y]^=changeto;
y=y+lowbit(y);
}

return;
}

int query(int x1,int y1,int x2,int y2){
int ans=0;

for(int i=x1;i<=x2;i++){
for(int j=y1-1;j>0;j-=lowbit(j)){
ans^=bit[i][j];
}
for(int j=y2;j>0;j-=lowbit(j)){
ans^=bit[i][j];
}
}

return ans;
}

int main(){
int t;
int q;
int tempnum;
int op;
int x1,y1,x2,y2;
int ans;
int changeto;

scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&q);

memset(bit,0,sizeof(bit));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&tempnum);
change(i,j,0,tempnum);
cnum[i][j]=tempnum;
}
}

for(int i=0;i<q;i++){
scanf("%d",&op);

if(op==1){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
ans=0;

ans=ans^query(x1,y1,x2,y2);
if(ans==0){
printf("No\n");
}
else{
printf("Yes\n");
}
}
else{
scanf("%d%d%d",&x1,&y1,&changeto);
change(x1,y1,cnum[x1][y1],changeto);
cnum[x1][y1]=changeto;
}
}
}

return 0;
}

真正的二维数组,果然速度快好多。

ac的代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 510

int bit

;
int cnum

;
int n,m;

int lowbit(int x){
return ((~x)+1)&x;
}

int query(int x,int y){
int ans=0;

for(int i=x;i;i=i-lowbit(i)){
for(int j=y;j;j=j-lowbit(j)){
ans^=bit[i][j];
}
}

return ans;
}

void change(int x,int y,int changeto){
for(int i=x;i<=n;i=i+lowbit(i)){
for(int j=y;j<=m;j=j+lowbit(j)){
bit[i][j]^=changeto;
}
}

return;
}

int main(){
int t;
int q;
int op;
int x1,y1,x2,y2;
int ans;
int changeto;

scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&q);

memset(bit,0,sizeof(bit));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&cnum[i][j]);
change(i,j,cnum[i][j]);
}
}

for(int i=0;i<q;i++){
scanf("%d",&op);

if(op==1){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);

ans=query(x2,y2)^query(x1-1,y2)^query(x2,y1-1)^query(x1-1,y1-1);
if(ans==0){
printf("No\n");
}
else{
printf("Yes\n");
}
}
else{
scanf("%d%d%d",&x1,&y1,&changeto);
change(x1,y1,changeto^cnum[x1][y1]);
cnum[x1][y1]=changeto;
}
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: