zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    <form:select>的使用
    存储过程-删除、新建索引
    java 反射常用总结
    java判断是否是数字
    jquery遍历数组添加行删除行
    oracle常用sql
    cxf (zhuan)
    linux 常用命令--个人小结一
    java发送邮件
    socket和webservice特点
  • 原文地址:https://www.cnblogs.com/Juve/p/11295567.html
Copyright © 2011-2022 走看看