HDU 4391 Paint The Wall
操作:
1. 将 a b 区间染上颜色z
2. 统计a b区间内颜色为z的点的个数
此题若用普通线段树会退化成O(n)
比赛时YY了一个map<int,int>的线段树 HLL的MLE了
赛后才知道可以YY剪枝过
方法:记录区间被染的最小颜色和最大颜色 若查询颜色不在范围内则return (数据水了)
更好的方法是标程上讲的分段Hash http://page.renren.com/601081183/note/867254911
剪枝版代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
using namespace std;
#define for if(0); else for
const int N=65537*2;
struct SegTree{
int a[N<<1],mi[N<<1],mx[N<<1];
int Q;
void init(int n,int c[]){
for(Q=1;Q<=n+2;Q<<=1);
memset(a,0,sizeof(a));
for(int i=Q+0;i<Q+n;i++) a[i]=mi[i]=mx[i]=c[i-Q];
for(int i=Q-1;i>=1;i--) pushup(i);
}
void pushup(int rt) {
a[rt]=a[rt<<1]==a[rt<<1|1]?a[rt<<1]:-1;
mi[rt]=min(mi[rt<<1],mi[rt<<1|1]);
mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void update_one(int rt,int x) {
a[rt]=mi[rt]=mx[rt]=x;
}
void pushdown(int rt) {
if(a[rt]!=-1) {
update_one(rt<<1,a[rt]);
update_one(rt<<1|1,a[rt]);
}
}
void update(int L,int R,int l,int r,int rt,int c) {
if(a[rt]==c) return;
if(L<=l && r<=R) {
update_one(rt,c);
return;
}
pushdown(rt);
if(rt>=Q) return;
int m=(l+r)>>1;
if(L<=m) update(L,R,l,m,rt<<1,c);
if(m<R) update(L,R,m+1,r,rt<<1|1,c);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt,int c) {
int ret=0;
if(L<=l && r<=R) {
if(c>=mi[rt]&&c<=mx[rt]){
int m=(l+r)>>1;
if(a[rt]!=-1) return (a[rt]==c)?r-l+1:0;
else return query(L,R,l,m,rt<<1,c)+query(L,R,m+1,r,rt<<1|1,c);
}else return 0;
}
if(rt>=Q) return ret;
pushdown(rt);
int m=(l+r)>>1;
if(L<=m) ret+=query(L,R,l,m,rt<<1,c);
if(m<R) ret+=query(L,R,m+1,r,rt<<1|1,c);
return ret;
}
}st;
int a[N];
int n,m;
int main() {
while(scanf("%d%d",&n,&m)!=EOF) {
for(int i=0;i<n;i++) scanf("%d",&a[i]);
st.init(n,a);
for(int i=0;i<m;i++) {
int cmd,l,r,c;
scanf("%d%d%d%d",&cmd,&l,&r,&c);
if(cmd==1){
st.update(l,r,0,st.Q-1,1,c);
}else {
printf("%d\n",st.query(l,r,0,st.Q-1,1,c));
}
}
}
return 0;
} 分段Hash版(用map<int,int>实现)代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <map>
using namespace std;
const int N=100010;
const int SQRTN=510;
int n,m;
int a[N];
map<int,int> hash[SQRTN];
int flag[SQRTN];
int block_size;
int block_num;
void rehash(int block_no) {
int st=block_no*block_size;
int ed=st+block_size-1;
if(ed>=n) ed=n-1;
hash[block_no].clear();
for(int i=st;i<=ed;i++) {
hash[block_no][a[i]]++;
}
flag[block_no]=-1;
}
void rebuild(int block_no) {
if(flag[block_no]!=-1) {
int st=block_no*block_size;
int ed=st+block_size-1;
if(ed>=n) ed=n-1;
for(int i=st;i<=ed;i++) a[i]=flag[block_no];
flag[block_no]=-1;
}
}
void build_hash() {
block_size = int(sqrt(n*1.0)+1.00001);
block_num = n/block_size + ( n%block_size !=0 ) ;
for(int i=0;i<block_num;i++) {
rehash(i);
}
}
void update_block(int block_no,int sta,int end,int z) {
if(z==flag[block_no]) return;
rebuild(block_no);
int st=block_no*block_size+sta;
int ed=block_no*block_size+end;
if(ed>=n) ed=n-1;
for(int i=st;i<=ed;i++) {
a[i]=z;
}
rehash(block_no);
}
int get_block(int block_no,int sta,int end,int z) {
if(flag[block_no]!=-1) {
return z==flag[block_no]?end-sta+1:0;
}
int st=block_no*block_size+sta;
int ed=block_no*block_size+end;
if(ed>=n) ed=n-1;
int ret=0;
for(int i=st;i<=ed;i++) {
if(a[i]==z) ret++;
}
return ret;
}
void update(int l,int r,int z) {
int lx=l/block_size;
int ly=l%block_size;
int rx=r/block_size;
int ry=r%block_size;
if(lx==rx){
update_block(lx,ly,ry,z);
}else{
update_block(lx,ly,block_size-1,z);
update_block(rx,0,ry,z);
}
for(int i=lx+1;i<=rx-1;i++) {
flag[i]=z;
}
}
int query(int l,int r,int z) {
int lx=l/block_size;
int ly=l%block_size;
int rx=r/block_size;
int ry=r%block_size;
int ret=0;
if(lx==rx){
ret+=get_block(lx,ly,ry,z);
}else{
ret+=get_block(lx,ly,block_size-1,z);
ret+=get_block(rx,0,ry,z);
}
for(int i=lx+1;i<=rx-1;i++) {
if(flag[i]!=-1){
if(z==flag[i]) ret+=block_size;
}else {
if(hash[i].find(z)!=hash[i].end()) ret+=hash[i][z];
}
}
return ret;
}
int main() {
while(scanf("%d%d",&n,&m)!=EOF) {
for(int i=0;i<n;i++) scanf("%d",&a[i]);
build_hash();
for(int i=0;i<m;i++) {
int cmd,l,r,z;
scanf("%d%d%d%d",&cmd,&l,&r,&z);
if(cmd==1) {
update(l,r,z);
}else if(cmd==2){
printf("%d\n",query(l,r,z));
}
}
}
return 0;
}