HDOJ 3911 Black And White
2016-05-20 00:09
399 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3911
此题也是属于线段树的区间合并问题,其实就是一个单纯的区间合并问题,有关线段树区间合并问题,大家可以看一道小编写的更基础的题POJ 3667 Hotel(其实这道题也是蛮基础的)。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 1000000+5;
int wsum[maxn<<2],lwsum[maxn],rwsum[maxn];
int bsum[maxn<<2],lbsum[maxn],rbsum[maxn];
int lazy[maxn];
int num[maxn];
void PushUp(int m,int rt)
{
lwsum[rt]=lwsum[rt<<1];
lbsum[rt]=lbsum[rt<<1];
rwsum[rt]=rwsum[rt<<1|1];
rbsum[rt]=rbsum[rt<<1|1];
if(lwsum[rt] == m-(m>>1)) lwsum[rt] += lwsum[rt<<1|1];
if(lbsum[rt] == m-(m>>1)) lbsum[rt] += lbsum[rt<<1|1];
if(rwsum[rt] == (m>>1)) rwsum[rt]+=rwsum[rt<<1];
if(rbsum[rt] == (m>>1)) rbsum[rt]+=rbsum[rt<<1];
wsum[rt] = max(wsum[rt<<1],wsum[rt<<1|1]);
bsum[rt]=max(bsum[rt<<1],bsum[rt<<1|1]);
wsum[rt] = max(wsum[rt], rwsum[rt<<1] + lwsum[rt<<1|1]);
bsum[rt] = max(bsum[rt], rbsum[rt<<1] + lbsum[rt<<1|1]);
}
void Change(int rt)
{
swap(bsum[rt],wsum[rt]);
swap(lwsum[rt],lbsum[rt]);
swap(rwsum[rt],rbsum[rt]);
}
void PushDown(int rt)
{
if(lazy[rt])
{
lazy[rt<<1]^=1;
lazy[rt<<1|1]^=1;
lazy[rt]=0;
Change(rt<<1);
Change(rt<<1|1);
}
}
void Build(int l,int r,int rt)
{
lazy[rt] = lbsum[rt] = rbsum[rt] = lwsum[rt] = rwsum[rt] = bsum[rt] = wsum[rt]=0;
if(l==r)
{
if(num[l]==1) bsum[rt] = lbsum[rt] = rbsum[rt] = 1;
else wsum[rt] = lwsum[rt] = rwsum[rt] = 1;
return ;
}
int mid = (l+r)>>1;
Build(lson);
Build(rson);
PushUp(r-l+1,rt);
}
void Update(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
lazy[rt]^=1;
Change(rt);
return ;
}
PushDown(rt);
int mid=(l+r)>>1;
if(L<=mid) Update(L,R,lson);
if(R>mid) Update(L,R,rson);
PushUp(r-l+1,rt);
}
int Query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return bsum[rt];
PushDown(rt);
int mid = (l+r)>>1;
if( R <= mid )
return Query(L, R, lson);
if( L > mid )
return Query(L, R, rson);
int t1 = Query(L, R, lson);
int t2 = Query(L, R, rson);
int a = min(mid-L+1, rbsum[rt<<1]);
int b = min(R-mid, lbsum[rt<<1|1]);
return max(max(t1, t2), a + b);
}
int main(){
int n,m,i,j,k,a,b,op;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++) scanf("%d",&num[i]);
Build(1,n,1);
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d",&op,&a,&b);
if(op==1)
Update(a,b,1,n,1);
else
{
int ans=Query(a,b,1,n,1);
printf("%d\n",ans);
}
}
}
return 0;
}
此题也是属于线段树的区间合并问题,其实就是一个单纯的区间合并问题,有关线段树区间合并问题,大家可以看一道小编写的更基础的题POJ 3667 Hotel(其实这道题也是蛮基础的)。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 1000000+5;
int wsum[maxn<<2],lwsum[maxn],rwsum[maxn];
int bsum[maxn<<2],lbsum[maxn],rbsum[maxn];
int lazy[maxn];
int num[maxn];
void PushUp(int m,int rt)
{
lwsum[rt]=lwsum[rt<<1];
lbsum[rt]=lbsum[rt<<1];
rwsum[rt]=rwsum[rt<<1|1];
rbsum[rt]=rbsum[rt<<1|1];
if(lwsum[rt] == m-(m>>1)) lwsum[rt] += lwsum[rt<<1|1];
if(lbsum[rt] == m-(m>>1)) lbsum[rt] += lbsum[rt<<1|1];
if(rwsum[rt] == (m>>1)) rwsum[rt]+=rwsum[rt<<1];
if(rbsum[rt] == (m>>1)) rbsum[rt]+=rbsum[rt<<1];
wsum[rt] = max(wsum[rt<<1],wsum[rt<<1|1]);
bsum[rt]=max(bsum[rt<<1],bsum[rt<<1|1]);
wsum[rt] = max(wsum[rt], rwsum[rt<<1] + lwsum[rt<<1|1]);
bsum[rt] = max(bsum[rt], rbsum[rt<<1] + lbsum[rt<<1|1]);
}
void Change(int rt)
{
swap(bsum[rt],wsum[rt]);
swap(lwsum[rt],lbsum[rt]);
swap(rwsum[rt],rbsum[rt]);
}
void PushDown(int rt)
{
if(lazy[rt])
{
lazy[rt<<1]^=1;
lazy[rt<<1|1]^=1;
lazy[rt]=0;
Change(rt<<1);
Change(rt<<1|1);
}
}
void Build(int l,int r,int rt)
{
lazy[rt] = lbsum[rt] = rbsum[rt] = lwsum[rt] = rwsum[rt] = bsum[rt] = wsum[rt]=0;
if(l==r)
{
if(num[l]==1) bsum[rt] = lbsum[rt] = rbsum[rt] = 1;
else wsum[rt] = lwsum[rt] = rwsum[rt] = 1;
return ;
}
int mid = (l+r)>>1;
Build(lson);
Build(rson);
PushUp(r-l+1,rt);
}
void Update(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
lazy[rt]^=1;
Change(rt);
return ;
}
PushDown(rt);
int mid=(l+r)>>1;
if(L<=mid) Update(L,R,lson);
if(R>mid) Update(L,R,rson);
PushUp(r-l+1,rt);
}
int Query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return bsum[rt];
PushDown(rt);
int mid = (l+r)>>1;
if( R <= mid )
return Query(L, R, lson);
if( L > mid )
return Query(L, R, rson);
int t1 = Query(L, R, lson);
int t2 = Query(L, R, rson);
int a = min(mid-L+1, rbsum[rt<<1]);
int b = min(R-mid, lbsum[rt<<1|1]);
return max(max(t1, t2), a + b);
}
int main(){
int n,m,i,j,k,a,b,op;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++) scanf("%d",&num[i]);
Build(1,n,1);
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d",&op,&a,&b);
if(op==1)
Update(a,b,1,n,1);
else
{
int ans=Query(a,b,1,n,1);
printf("%d\n",ans);
}
}
}
return 0;
}
相关文章推荐
- IOS开发总结之文件下载(大文件下载)
- selenium+python笔记6
- 使用SignalR 提高B2C商城用户体验1
- Java实现简单数据结构之二叉树结构排序 binary tree
- UML用例图说明
- HDU 4725 The Shortest Path in Nya Graph (最短路拆点建图)
- <LeetCode OJ> 349 / 350 Intersection of Two Arrays(I / II)
- 数据流重定向
- px4 middleware and architecture
- 最长回文串 O(n)复杂度(manacher算法)
- java基础第三天_数组
- 基于TCP/IP协议的网络攻击
- mini2440NFS启动,VFS: Unable to mount root fs via NFS, trying floppy.
- 1,架构总设计及安全思路
- Java基础之比较器 Comparable和Comparator
- 华为云服务产品之精华问题大集烩(一)
- 我们是如何使用 Electron 构建 Linux 桌面应用程序的
- 提高程序员开发效率的必备工具(最新版本)
- rem : web app适配的秘密武器
- 如何选择jQuery版本 1.x? 2.x? 3.x?