HZOI20190803 B题
题目:https://www.cnblogs.com/Juve/articles/11295333.html
话说这题方法挺多
40分:暴力
65:莫队,你会T得飞起
我考场上没打出带修莫队,没有修改的·跑普通莫队,有修改的,跑暴力(反正都是离线)
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #define MAXN 300005 //#define int long long #define re register using namespace std; int n,m,a[MAXN],rk[MAXN]; bool appear[MAXN],flag=0; int num=0,sum=0,blo,block[MAXN],l=1,r=0; struct node{ int l,r,id,t,val,opt; friend bool operator < (node a,node b){ return block[a.l]==block[b.l]?a.r<b.r:a.l<b.l; } }ask[MAXN]; struct node1{ int pos,val,t,opt; }change[MAXN]; struct node2{ int l,r,val,opt,pos; }vio[MAXN]; int cnt[MAXN],ans[MAXN]; void add(int x){ cnt[x]++; } void del(int x){ cnt[x]--; } signed main(){ scanf("%d%d",&n,&m); blo=sqrt(n); for(re int i=1;i<=n;i++){ scanf("%d",&a[i]); block[i]=i/blo+1; if(appear[a[i]]){ flag=1; } appear[a[i]]=1; } if(!flag){ for(re int i=1;i<=n;i++) rk[a[i]]=i; for(re int i=1,opt;i<=m;i++){ scanf("%d",&opt); if(opt==1){ re int l,r,col; scanf("%d%d%d",&l,&r,&col); if(l<=rk[col]&&rk[col]<=r) puts("1"); else puts("0"); }else{ re int x; scanf("%d",&x); rk[a[x]]=x+1; rk[a[x+1]]=x; swap(a[x],a[x+1]); } } return 0; } for(re int i=1,opt;i<=m;i++){ scanf("%d",&opt); if(opt==1){ ask[++num].opt=opt; scanf("%d%d%d",&ask[num].l,&ask[num].r,&ask[num].val); ask[num].t=sum; ask[num].id=num; vio[i].opt=opt; vio[i].l=ask[num].l,vio[i].r=ask[num].r,vio[i].val=ask[num].val; }else{ change[++sum].opt=opt; re int x; scanf("%d",&x); change[sum].pos=x,change[sum].val=a[x+1]; change[++sum].opt=opt; change[sum].pos=x+1,change[sum].val=a[x]; vio[i].opt=opt,vio[i].pos=x; } } if(sum==0){ sort(ask+1,ask+num+1); for(re int i=1;i<=num;i++){ while(l<ask[i].l){ cnt[a[l++]]--; //del(a[l++]); } while(l>ask[i].l){ cnt[a[--l]]++; //add(a[--l]); } while(r<ask[i].r){ cnt[a[++r]]++; //add(a[++r]); } while(r>ask[i].r){ cnt[a[r--]]--; //del(a[r--]); } ans[ask[i].id]=cnt[ask[i].val]; } for(re int i=1;i<=num;i++){ printf("%d\n",ans[i]); } return 0; } else{ for(re int i=1;i<=m;i++){ if(vio[i].opt==1){ re int col=vio[i].val,ans=0; for(re int j=vio[i].l;j<=vio[i].r;j++){ if(a[j]==col) ans++; } printf("%d\n",ans); }else{ swap(a[vio[i].pos],a[vio[i].pos+1]); } } } return 0; }
100:
vector排序+二分查找
#include<cstdio> #include<vector> #include<algorithm> #define N 300050 using namespace std; int n,m; int a[N]; vector<int>v[N]; int main() { scanf("%d%d",&n,&m); int ok1=1,ok2=1; for(int i=1;i<=n;++i) { scanf("%d",&a[i]); v[a[i]].push_back(i); } int opt,l,r,c,x; while(m--) { scanf("%d",&opt); if(opt==1) { scanf("%d%d%d",&l,&r,&c); l=lower_bound(v[c].begin(),v[c].end(),l)-v[c].begin(); r=upper_bound(v[c].begin(),v[c].end(),r)-v[c].begin(); printf("%d\n",r-l); continue; } scanf("%d",&x); l=a[x],r=a[x+1]; v[l][lower_bound(v[l].begin(),v[l].end(),x)-v[l].begin()]=x+1; v[r][lower_bound(v[r].begin(),v[r].end(),x+1)-v[r].begin()]=x; swap(a[x],a[x+1]); } return 0; }
或者。。。主席树?
就是查找排名
#include<bits/stdc++.h> using namespace std; #define cri const register int const int L=1<<20|1; char buffer[L],*S,*T; #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) inline int read(){ int a=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') a=(a<<3)+(a<<1)+ch-'0',ch=getchar(); return a; } int a[3000010],rt[3000010],t,now; int ls[20000010],rs[20000010],da[20000010],cnt; void insert(int &k,cri l,cri r,cri x,cri y){ if(!k) k=++cnt; if(l==r){ da[k]+=y; return; } int mid=l+r>>1; if(x<=mid) insert(ls[k],l,mid,x,y); else insert(rs[k],mid+1,r,x,y); da[k]=da[ls[k]]+da[rs[k]]; } void query(cri k,cri l,cri r,cri L,cri R){ if(!k||da[k]<=0) return; if(l>=L&&r<=R){ if(da[k]>0) now+=da[k]; return; } int mid=l+r>>1; if(L<=mid) query(ls[k],l,mid,L,R); if(R>mid) query(rs[k],mid+1,r,L,R); } int main(){ // freopen("t.in","r",stdin); // freopen("w.out","w",stdout); int n,m,x,y,z,k,ans,ma=0; scanf("%d%d",&n,&m);t=sqrt(n); for(int i=1;i<=n;i++) a[i]=read(),insert(rt[a[i]],1,n,i,1); while(m--){ x=read();ans=0; if(x==1){ y=read(),z=read(),k=read(); if(y>z) swap(y,z); now=0; query(rt[k],1,n,y,z); printf("%d\n",now); } else{ y=read(); insert(rt[a[y]],1,n,y,-1); insert(rt[a[y+1]],1,n,y+1,-1); insert(rt[a[y]],1,n,y+1,1); insert(rt[a[y+1]],1,n,y,1); swap(a[y],a[y+1]); } } return 0; }
也可以像我一样,来个平衡树
这里用我的平衡树思路将一下
我们给每个颜色建一个平衡树,将该颜色所在的位置插入平衡树,
修改就暴力del和ins,
查询就是找区间端点的排名,
若我们要询问[L,R]中col的出现次数,那么我们在col的平衡树中查询R+1和L的排名,相减就是答案
好像还要卡常。。。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #define MAXN 1000005 #define re register using namespace std; int n,m,a[MAXN],root[MAXN]; inline int read(){ int x=0;char ch=getchar(); while(ch<'0'||ch>'9'){ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x; } struct Treap{ int tot; struct node{ int l,r,data,val,size; }tr[MAXN]; Treap(){tot=1;} inline void update(re int p){ tr[p].size=tr[tr[p].l].size+tr[tr[p].r].size+1; } inline int New(re int val){ re int x=++tot; tr[x].val=val; tr[x].data=rand(); tr[x].size=1; return x; } inline void merge(re int &root,re int a,re int b){ if(!a||!b){ root=a+b; return ; } if(tr[a].data<tr[b].data){ root=a; merge(tr[root].r,tr[a].r,b); } else{ root=b; merge(tr[root].l,a,tr[b].l); } update(root); } inline void split(re int x,re int &a,re int &b,re int val){ if(!x){ a=b=0; return ; } if(tr[x].val<=val){ a=x; split(tr[x].r,tr[a].r,b,val); } else{ b=x; split(tr[x].l,a,tr[b].l,val); } update(x); } inline int get_rank(re int &root,re int val){ int x=0,y=0; split(root,x,y,val-1); int ans=tr[x].size+1; merge(root,x,y); return ans; } inline void ins(re int &root,re int val){ int x=0,y=0; split(root,x,y,val); merge(x,x,New(val)); merge(root,x,y); } inline void del(re int &root,re int val){ int x=0,y=0,z=0; split(root,x,y,val); split(x,x,z,val-1); merge(z,tr[z].l,tr[z].r); merge(x,x,z); merge(root,x,y); } }treap; signed main(){ n=read(),m=read(); for(re int i=1;i<=n;i++){ a[i]=read(); treap.ins(root[a[i]],i); } for(re int i=1,opt;i<=m;i++){ opt=read(); if(opt==1){ re int l,r,col; l=read(),r=read(),col=read(); printf("%d\n",treap.get_rank(root[col],r+1)-treap.get_rank(root[col],l)); }else{ re int pos; pos=read(); if(a[pos]==a[pos+1]) continue; treap.del(root[a[pos]],pos); treap.del(root[a[pos+1]],pos+1); swap(a[pos],a[pos+1]); treap.ins(root[a[pos]],pos); treap.ins(root[a[pos+1]],pos+1); } } return 0; }