zoukankan      html  css  js  c++  java
  • LOJ 6278 数列分块入门2

    【题解】

      分块。块内排序。块内二分出第一个大于等于c的数。

      

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define N 500010
    #define rg register
    using namespace std;
    int n,m,opt,l,r,c,block,bl[N],tag[N];
    struct rec{
    	int data,pos;
    }a[N];
    inline int read(){
    	int k=0,f=1; char c=getchar();
    	while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    	while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    	return k*f;
    }
    inline bool cmp(rec x,rec y){return x.data<y.data;}
    inline int find(int pos,int x){
    	int l=(pos-1)*block+1,r=pos*block, ll=l;
    	while(l<r){
    		int mid=(l+r+1)>>1;
    		if(a[mid].data<x) l=mid;
    		else r=mid-1;
    	}
    	if(a[l].data>=x) return 0;
    	return l-ll+1;
    }
    int main(){
    	n=read(); block=sqrt(n); 
    	for(rg int i=1;i<=n;i++) a[i].data=read(),a[i].pos=i;
    	for(rg int i=1;i<=n;i++) bl[i]=(i-1)/block+1;
    	for(rg int i=1;i<=block+1;i++) sort(a+(i-1)*block+1,a+min(i*block,n)+1,cmp);
    	for(rg int j=1;j<=n;j++){
    		if((opt=read())==0){
    			l=read(); r=read(); c=read();
    			int st=bl[l]+1,ed=bl[r]-1;
    			for(rg int i=st;i<=ed;i++) tag[i]+=c;
    			if(bl[l]==bl[r]){
    				int x=(bl[l]-1)*block+1,y=min(bl[l]*block,n);
    				for(rg int i=x;i<=y;i++) if(a[i].pos>=l&&a[i].pos<=r) a[i].data+=c;
    				sort(a+x,a+y+1,cmp);
    				continue;
    			}
    			int x=(bl[l]-1)*block+1,y=min(bl[l]*block,n);
    			for(rg int i=x;i<=y;i++)
    				if(a[i].pos>=l) a[i].data+=c;
    			sort(a+x,a+y+1,cmp);
    			x=(bl[r]-1)*block+1,y=min(bl[r]*block,n);
    			for(rg int i=x;i<=y;i++)
    				if(a[i].pos<=r) a[i].data+=c;
    			sort(a+x,a+y+1,cmp);
    		}
    		else{
    			l=read(); r=read(); c=read(); c*=c;
    			int st=bl[l]+1,ed=bl[r]-1,ans=0;
    			for(rg int i=st;i<=ed;i++) ans+=find(i,c-tag[i]);
    			if(bl[l]==bl[r]){
    				for(rg int i=(bl[l]-1)*block+1;i<=bl[l]*block;i++)
    					if(a[i].pos>=l&&a[i].pos<=r&&a[i].data+tag[bl[l]]<c) ans++;
    				printf("%d
    ",ans); continue;
    			}
    			int x=(bl[l]-1)*block+1,y=min(bl[l]*block,n);
    			for(rg int i=x;i<=y;i++)
    				if(a[i].pos>=l&&a[i].data+tag[bl[l]]<c) ans++;
    			x=(bl[r]-1)*block+1,y=min(bl[r]*block,n);
    			for(rg int i=x;i<=y;i++)
    				if(a[i].pos<=r&&a[i].data+tag[bl[r]]<c) ans++;
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    双指针
    二分查找
    二叉树
    递归思想
    排序算法
    Java常用集合使用方法总结
    攻防世界-PHP文件包含
    正则表达式随笔
    ts 函数
    ts 联合类型
  • 原文地址:https://www.cnblogs.com/DriverLao/p/8470829.html
Copyright © 2011-2022 走看看