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
",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
",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
",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
",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
",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;
}
原文地址:https://www.cnblogs.com/Juve/p/11295567.html