COJ967 WZJ的数据结构(负三十三)
WZJ的数据结构(负三十三) |
难度级别:C; 运行时间限制:7000ms; 运行空间限制:262144KB; 代码长度限制:2000000B |
试题描述
|
请你设计一个数据结构,完成以下功能: 给定一个大小为N的整数组A,要求你回答执行N次操作。操作分两种: 操作1:每次操作给你l,r,v三个参数,求Al至Ar中值<=v的个数。 操作2:每次操作给你l,r,v三个参数,将Al至Ar所有数的值设为v。 |
输入
|
第一行为一个正整数N。
第二行为N个整数Ai。 接下来N行每行4个正整数t,l,r,v。若t=2表示操作1,t=1表示操作2。 |
输出
|
对每个操作1输出结果。
|
输入示例
|
6
1 2 2 1 2 3 2 1 4 2 2 1 4 1 1 2 4 1 2 1 4 1 1 3 5 2 2 2 5 2 |
输出示例
|
4
2 4 4 |
其他说明
|
1<=N<=200000
1<=Ai,v<=10^9 |
XYZ大爷论文题“一个简单的序列问题”。
一上午的青春全部奉献给这道题了(3棵线段树调得我要报警)。
先将区间修改转化成带删除的区间插入,用一棵线段树来做。
再用线段树分治将问题转化成静态问题,用一棵线段树和2个nlogn的邻接表。
最后排序后转化成区间加与区间查询的问题,用一棵线段树来做。
说起来真是简单呢!
#include<cstdio> #include<cctype> #include<queue> #include<cmath> #include<cstring> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ren for(int i=first[x];i!=-1;i=next[i]) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=400010; struct Query { int tp,l,r,x,begin,end,id; bool operator < (const Query& ths) const {return begin<ths.begin;} }Q[maxn],Q2[maxn*3]; struct Solver { int id,l,r,x; bool operator < (const Solver& ths) const {return x<ths.x||(x==ths.x&&id<ths.id);} }A[maxn*3]; int n,ans[maxn],m; int setv[maxn*3],is[maxn*3]; void pushdown(int o) { int lc=o<<1,rc=lc|1; if(setv[o]) { setv[lc]=setv[rc]=setv[o]; is[lc]=is[rc]=1; setv[o]=0; } } int lastv,L,R; void find(int o,int l,int r,int v) { if(!is[o]) return; if(setv[o]) { if(setv[o]==lastv) R=r; else { if(lastv!=-1) Q2[++m]=(Query){1,L,R,Q[lastv].x,lastv,v-1,Q[lastv].id}; lastv=setv[o];L=l;R=r; } setv[o]=0; } else if(l<r) { int mid=l+r>>1,lc=o<<1,rc=lc|1; find(lc,l,mid,v);find(rc,mid+1,r,v); } is[o]=0; } void update(int o,int l,int r,int ql,int qr,int v) { if(ql<=l&&r<=qr) find(o,l,r,v),setv[o]=v; else { pushdown(o); int mid=l+r>>1,lc=o<<1,rc=lc|1; if(ql<=mid) update(lc,l,mid,ql,qr,v); if(qr>mid) update(rc,mid+1,r,ql,qr,v); } is[o]=1; } int first1[maxn*3],next1[maxn*20],id1[maxn*20],ToT1; int first2[maxn*3],next2[maxn*20],id2[maxn*20],ToT2,N; void query(int o,int l,int r,int pos,int v) { N=max(N,o); id1[++ToT1]=v;next1[ToT1]=first1[o];first1[o]=ToT1; if(l==r) return; int mid=l+r>>1,lc=o<<1,rc=lc|1; if(pos<=mid) query(lc,l,mid,pos,v); else query(rc,mid+1,r,pos,v); } void modify(int o,int l,int r,int ql,int qr,int v) { N=max(N,o); if(ql<=l&&r<=qr) { id2[++ToT2]=v;next2[ToT2]=first2[o];first2[o]=ToT2; } else { int mid=l+r>>1,lc=o<<1,rc=lc|1; if(ql<=mid) modify(lc,l,mid,ql,qr,v); if(qr>mid) modify(rc,mid+1,r,ql,qr,v); } } int addv[maxn*3],sumv[maxn*3]; void pushdown2(int o,int l,int r) { int mid=l+r>>1,lc=o<<1,rc=lc|1; if(addv[o]) { addv[lc]+=addv[o];addv[rc]+=addv[o]; sumv[lc]+=addv[o]*(mid-l+1);sumv[rc]+=addv[o]*(r-mid); addv[o]=0; } } void update2(int o,int l,int r,int ql,int qr,int v) { int mid=l+r>>1,lc=o<<1,rc=lc|1; if(ql<=l&&r<=qr) addv[o]+=v; else { pushdown2(o,l,r); if(ql<=mid) update2(lc,l,mid,ql,qr,v); if(qr>mid) update2(rc,mid+1,r,ql,qr,v); } if(l<r) sumv[o]=sumv[lc]+sumv[rc]; else sumv[o]=0; if(addv[o]) sumv[o]+=addv[o]*(r-l+1); } int query2(int o,int l,int r,int ql,int qr) { if(ql<=l&&r<=qr) return sumv[o]; pushdown2(o,l,r); int mid=l+r>>1,lc=o<<1,rc=lc|1,ans=0; if(ql<=mid) ans+=query2(lc,l,mid,ql,qr); if(qr>mid) ans+=query2(rc,mid+1,r,ql,qr); return ans; } int tmp[maxn]; int main() { n=read(); rep(i,1,n) Q[Q[i].id=i].tp=1,Q[i].l=i,Q[i].r=i,Q[i].x=read(); rep(i,n+1,2*n) Q[Q[i].id=i].tp=read(),Q[i].l=read(),Q[i].r=read(),Q[i].x=read(); n<<=1; Q[n+1].tp=1;Q[n+1].l=1;Q[n+1].r=n>>1; rep(i,1,n+1) { if(Q[i].tp==1) { lastv=-1; update(1,1,n>>1,Q[i].l,Q[i].r,i); if(lastv!=-1) Q2[++m]=(Query){1,L,R,Q[lastv].x,lastv,i-1,Q[lastv].id}; } else Q2[++m]=Q[i],Q2[m].begin=Q2[m].end=i; } rep(i,1,m) { if(Q2[i].tp==1) modify(1,1,n,Q2[i].begin,Q2[i].end,i); else query(1,1,n,Q2[i].begin,i); } rep(i,1,N) if(first1[i]&&first2[i]) { int cnt=0; for(int j=first1[i];j;j=next1[j]) A[++cnt]=(Solver){Q2[id1[j]].id,Q2[id1[j]].l,Q2[id1[j]].r,Q2[id1[j]].x}; for(int j=first2[i];j;j=next2[j]) A[++cnt]=(Solver){0,Q2[id2[j]].l,Q2[id2[j]].r,Q2[id2[j]].x}; sort(A+1,A+cnt+1); rep(j,1,cnt) { if(!A[j].id) update2(1,1,n>>1,A[j].l,A[j].r,1); else ans[A[j].id]+=query2(1,1,n>>1,A[j].l,A[j].r); } rep(j,1,cnt) if(!A[j].id) update2(1,1,n>>1,A[j].l,A[j].r,-1); } rep(i,1,n) if(Q[i].tp==2) printf("%d\n",ans[i]); return 0; }
8.6重写了一遍,30min写完,WA了两处233.
错误:
void pushdown(int o) { int lc=o<<1,rc=lc|1; if(setv[o]) { setv[lc]=setv[rc]=1;//setv[o] is[lc]=is[rc]=1; setv[o]=0; } } int query(int o,int l,int r,int ql,int qr) { if(ql<=l&&r<=qr) return sumv[o]; //pushdown(o,l,r); int mid=l+r>>1,lc=o<<1,rc=lc|1,res=0; if(ql<=mid) res+=query(lc,l,mid,ql,qr); if(qr>mid) res+=query(rc,mid+1,r,ql,qr); return res; }
8.10啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊标程被分块虐了!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<queue> #include<cstring> #define PAU putchar(' ') #define ENT putchar('\n') using namespace std; const int maxn=200000+10,maxb=500,inf=-1u>>1; int z[maxn],st[maxb],en[maxb],size,n,A[maxn],B[maxn],set[maxb],siz[maxb]; inline int read(){ int x=0,sig=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=0; for(;isdigit(ch);ch=getchar())x=10*x+ch-'0'; return sig?x:-x; } inline void write(int x){ if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; } void build(int b){ for(int i=st[b];i<=en[b];i++)B[i]=A[i];sort(B+st[b],B+en[b]+1);return; } void down(int b){ if(set[b]!=inf){for(int i=st[b];i<=en[b];i++)A[i]=B[i]=set[b];set[b]=inf;}return; } void sett(int L,int R,int cv){ down(z[L]);for(int i=L;i<=R;i++)A[i]=cv;build(z[L]);return; } void setb(int L,int R,int cv){ for(int b=L;b<=R;b++)set[b]=cv;return; } void seto(int ql,int qr,int cv){ if(z[ql]==z[qr])sett(ql,qr,cv); else sett(ql,en[z[ql]],cv),setb(z[ql]+1,z[qr]-1,cv),sett(st[z[qr]],qr,cv);return; } int queryb(int L,int R,int cv){ int ans=0; for(int b=L;b<=R;b++){ if(set[b]!=inf){ if(set[b]<=cv)ans+=siz[b]; }else ans+=upper_bound(B+st[b],B+en[b]+1,cv)-B-st[b]; }return ans; } int queryt(int L,int R,int cv){ int ans=0; if(set[z[L]]!=inf){ if(set[z[L]]<=cv)ans+=(R-L+1); }else for(int i=L;i<=R;i++)if(A[i]<=cv)ans++; return ans; } int queryo(int ql,int qr,int cv){ if(z[ql]==z[qr])return queryt(ql,qr,cv); else return queryt(ql,en[z[ql]],cv)+queryb(z[ql]+1,z[qr]-1,cv)+queryt(st[z[qr]],qr,cv); } void init(){ n=read();size=sqrt((double)n*0.9);int tp,ql,qr,cv; for(int i=1;i<=n;i++){ A[i]=B[i]=read(); z[i]=(i-1)/size+1; if(!st[z[i]])st[z[i]]=i; en[z[i]]=i; } for(int b=1;b<=z[n];b++)build(b),set[b]=inf,siz[b]=en[b]-st[b]+1; for(int i=1;i<=n;i++){ tp=read();ql=read();qr=read();cv=read(); if(tp==2)write(queryo(ql,qr,cv)),ENT; else seto(ql,qr,cv); } return; } void work(){ return; } void print(){ return; } int main(){init();work();print();return 0;}