区间更新 zoj3911
2015-10-18 18:48
253 查看
哎,没什么坑点,一个简单的区间更新题,但是改了好几天没改对,最终还是过了~~发个纪念下
泪奔。。。
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define N 100010
#define MAXN 10000010
using namespace std;
struct dd
{
int cnt;//这个区间内素数的个数
int l,r;
int val;//存的是素数
int flag;//区间更新的标记
}tree[N<<2];
int isp[MAXN];
void inint()//素数打表
{
memset(isp,0,sizeof(isp));
isp[0]=isp[1]=1;
for(int i=2;i<MAXN;i++)
{
if(!isp[i])
{
if(i>MAXN/i)
continue;
for(int j=i*i;j<MAXN;j+=i)
isp[j]=1;
}
}
}
void push_up(int k)//更新父亲节点
{
tree[k].cnt=tree[k<<1].cnt+tree[k<<1|1].cnt;
}
void push_down(int k)//区间更新
{
if(tree[k].flag)
{
tree[k<<1].flag=tree[k<<1|1].flag=tree[k].flag;
tree[k<<1].val=tree[k<<1|1].val=tree[k].val;
tree[k<<1].cnt=(isp[tree[k].flag])?0:tree[k<<1].r-tree[k<<1].l+1;
tree[k<<1|1].cnt=(isp[tree[k].flag])?0:tree[k<<1|1].r-tree[k<<1|1].l+1;
tree[k].flag=0;
}
}
void build(int l,int r,int k)//建树
{
tree[k].l=l;
tree[k].r=r;
tree[k].cnt=0;
tree[k].flag=0;
tree[k].val=0;
if(l==r)
{
int val;
scanf("%d",&val);
tree[k].val=val;
if(!isp[val])
tree[k].cnt=1;
return;
}
int mid=(l+r)/2;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
push_up(k);
}
void update1(int val,int pos,int k)//更新一个节点
{
if(tree[k].l==tree[k].r&&tree[k].l==pos)
{
tree[k].val+=val;
if(!isp[tree[k].val])
tree[k].cnt=1;
else
tree[k].cnt=0;
return;
}
push_down(k);//这里的push_down竟然没加!!!泪奔的是,还是自己删掉的,好久才发现
int mid=(tree[k].l+tree[k].r)/2;
if(pos<=mid)
update1(val,pos,k<<1);
else
update1(val,pos,k<<1|1);
push_up(k);
}
void update2(int val,int l,int r,int k)//更新区间
{
if(tree[k].l==l&&tree[k].r==r)
{
tree[k].cnt=(isp[val])?0:tree[k].r-tree[k].l+1;//开始的时候这里的cnt值也忘了改
tree[k].val=val;
tree[k].flag=val;
return;
}
push_down(k);
int mid=(tree[k].l+tree[k].r)/2;
if(r<=mid) update2(val,l,r,k<<1);
else if(l>mid) update2(val,l,r,k<<1|1);
else
{
update2(val,l,mid,k<<1);
update2(val,mid+1,r,k<<1|1);
}
push_up(k);
}
int query(int k,int l,int r)//询问区间内的元素数
{
int sum=0;
if(tree[k].l==l&&tree[k].r==r)
{
return tree[k].cnt;
}
push_down(k);
int mid=(tree[k].l+tree[k].r)/2;
if(mid>=r)
sum+=query(k<<1,l,r);
else if(l>mid)
sum+=query(k<<1|1,l,r);
else
{
sum+=query(k<<1,l,mid);
sum+=query(k<<1|1,mid+1,r);
}
push_up(k);
return sum;
}
int main()
{
int t,n,q;
char op[5];
//printf("%d\n",2|1);
inint();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
build(1,n,1);
while(q--)
{
scanf("%s",op);
if(op[0]=='A')//pos这个点的元素加val
{
int val,pos;
scanf("%d%d",&val,&pos);
update1(val,pos,1);
}
else if(op[0]=='R')//l,r区间内的元素都改为val
{
int val,l,r;
scanf("%d%d%d",&val,&l,&r);
update2(val,l,r,1);
}
else if(op[0]=='Q')//询问区间内的元素数
{
int l,r;
scanf("%d%d",&l,&r);
int sum=query(1,l,r);
printf("%d\n",sum);
}
}
}
return 0;
}
泪奔。。。
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define N 100010
#define MAXN 10000010
using namespace std;
struct dd
{
int cnt;//这个区间内素数的个数
int l,r;
int val;//存的是素数
int flag;//区间更新的标记
}tree[N<<2];
int isp[MAXN];
void inint()//素数打表
{
memset(isp,0,sizeof(isp));
isp[0]=isp[1]=1;
for(int i=2;i<MAXN;i++)
{
if(!isp[i])
{
if(i>MAXN/i)
continue;
for(int j=i*i;j<MAXN;j+=i)
isp[j]=1;
}
}
}
void push_up(int k)//更新父亲节点
{
tree[k].cnt=tree[k<<1].cnt+tree[k<<1|1].cnt;
}
void push_down(int k)//区间更新
{
if(tree[k].flag)
{
tree[k<<1].flag=tree[k<<1|1].flag=tree[k].flag;
tree[k<<1].val=tree[k<<1|1].val=tree[k].val;
tree[k<<1].cnt=(isp[tree[k].flag])?0:tree[k<<1].r-tree[k<<1].l+1;
tree[k<<1|1].cnt=(isp[tree[k].flag])?0:tree[k<<1|1].r-tree[k<<1|1].l+1;
tree[k].flag=0;
}
}
void build(int l,int r,int k)//建树
{
tree[k].l=l;
tree[k].r=r;
tree[k].cnt=0;
tree[k].flag=0;
tree[k].val=0;
if(l==r)
{
int val;
scanf("%d",&val);
tree[k].val=val;
if(!isp[val])
tree[k].cnt=1;
return;
}
int mid=(l+r)/2;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
push_up(k);
}
void update1(int val,int pos,int k)//更新一个节点
{
if(tree[k].l==tree[k].r&&tree[k].l==pos)
{
tree[k].val+=val;
if(!isp[tree[k].val])
tree[k].cnt=1;
else
tree[k].cnt=0;
return;
}
push_down(k);//这里的push_down竟然没加!!!泪奔的是,还是自己删掉的,好久才发现
int mid=(tree[k].l+tree[k].r)/2;
if(pos<=mid)
update1(val,pos,k<<1);
else
update1(val,pos,k<<1|1);
push_up(k);
}
void update2(int val,int l,int r,int k)//更新区间
{
if(tree[k].l==l&&tree[k].r==r)
{
tree[k].cnt=(isp[val])?0:tree[k].r-tree[k].l+1;//开始的时候这里的cnt值也忘了改
tree[k].val=val;
tree[k].flag=val;
return;
}
push_down(k);
int mid=(tree[k].l+tree[k].r)/2;
if(r<=mid) update2(val,l,r,k<<1);
else if(l>mid) update2(val,l,r,k<<1|1);
else
{
update2(val,l,mid,k<<1);
update2(val,mid+1,r,k<<1|1);
}
push_up(k);
}
int query(int k,int l,int r)//询问区间内的元素数
{
int sum=0;
if(tree[k].l==l&&tree[k].r==r)
{
return tree[k].cnt;
}
push_down(k);
int mid=(tree[k].l+tree[k].r)/2;
if(mid>=r)
sum+=query(k<<1,l,r);
else if(l>mid)
sum+=query(k<<1|1,l,r);
else
{
sum+=query(k<<1,l,mid);
sum+=query(k<<1|1,mid+1,r);
}
push_up(k);
return sum;
}
int main()
{
int t,n,q;
char op[5];
//printf("%d\n",2|1);
inint();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
build(1,n,1);
while(q--)
{
scanf("%s",op);
if(op[0]=='A')//pos这个点的元素加val
{
int val,pos;
scanf("%d%d",&val,&pos);
update1(val,pos,1);
}
else if(op[0]=='R')//l,r区间内的元素都改为val
{
int val,l,r;
scanf("%d%d%d",&val,&l,&r);
update2(val,l,r,1);
}
else if(op[0]=='Q')//询问区间内的元素数
{
int l,r;
scanf("%d%d",&l,&r);
int sum=query(1,l,r);
printf("%d\n",sum);
}
}
}
return 0;
}
相关文章推荐
- 黑马程序员——OC学习笔记06 内存管理2
- 题目11:MySQL---------Duplicate Emails
- mysql计算指定的时间TPS
- 16进制转10进制算法
- 【bzoj3175】【TJOI2013】【攻击装置】【二分图最大独立集】
- 信息安全系统设计基础第五周学习总结
- XMPP开发adiumclient登陆
- ios学习之pickerview的使用
- MDK4.74中编译时Error:User Command terminated, Exit-Code = 1
- 二进制和16进制转换
- 结对编程作业
- explain优化(索引优化)--------方法
- 三思考,实现自己定义404页:Tomcat、SpringMVC精确匹配、重写DispatchServlet
- poj1789(prim)
- java web(下载以及下载编码问题)
- HttpClient 版本变化 转载
- coredata入门
- 【bzoj2464】【中山市选2009】【小明的游戏】【spfa】
- HDOJ 1576 A/B (扩展欧几里得)
- 未解决的问题:关于toolbar和键盘一起上移的问题