zoukankan      html  css  js  c++  java
  • 扫描线

    港真考试之前我以为自己是会扫描线的QAQ、、、
    然后就被ta的板子锤自闭了。。。
    不知道是哪里来的错觉。。。

    矩形周长

    扫描线的时候存一下这个节点被覆盖了多少次(!!
    然后就可以求长度和修改啦
    横向扫一遍,纵向扫一遍就是整个周长

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #define M 10001
    #define MP make_pair
    using namespace std;
    
    int n,m,k,len[1000001],num[1000001],ans,z;
    vector <pair<int,int> >qb[100001],qe[100001];
    struct vv
    {
    	int l1,l2,r1,r2;
    } a[1000001];
    void add(int now,int l,int r,int L,int R,int z)
    {
    	if(l>=L && r<=R)
    	{
    		num[now]+=z;
    		if(num[now]) len[now]=r-l+1;
    		else len[now]=len[now*2]+len[now*2+1];
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(mid>=L) add(now*2,l,mid,L,R,z);
    	if(mid<R) add(now*2+1,mid+1,r,L,R,z);
    	if(!num[now]) len[now]=len[now*2]+len[now*2+1];
    	else len[now]=r-l+1;
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d%d%d%d",&a[i].l1,&a[i].l2,&a[i].r1,&a[i].r2);
    		a[i].l1+=M, a[i].l2+=M, a[i].r1+=M, a[i].r2+=M;
    		qb[a[i].l1].push_back(MP(a[i].l2,a[i].r2));
    		qe[a[i].r1].push_back(MP(a[i].l2,a[i].r2));
    	}
    	for(int i=1;i<=M+M;i++) 
    	{
    		for(int j=0;j<qb[i].size();j++) add(1,1,M+M,qb[i][j].first,qb[i][j].second-1,1);  ans+=2*abs(len[1]-z);
    		for(int j=0;j<qe[i].size();j++) add(1,1,M+M,qe[i][j].first,qe[i][j].second-1,-1); z=len[1];
    		qb[i].clear(); qe[i].clear();
    	}
    	memset(len,0,sizeof(len));
    	memset(num,0,sizeof(num));
    	for(int i=1;i<=n;i++)
    	{
    		qb[a[i].l2].push_back(MP(a[i].l1,a[i].r1));
    		qe[a[i].r2].push_back(MP(a[i].l1,a[i].r1));
    	}
    	for(int i=1;i<=M+M;i++) 
    	{
    		for(int j=0;j<qb[i].size();j++) add(1,1,M+M,qb[i][j].first,qb[i][j].second-1,1);  ans+=2*abs(len[1]-z); 
    		for(int j=0;j<qe[i].size();j++) add(1,1,M+M,qe[i][j].first,qe[i][j].second-1,-1); z=len[1];		
    		qb[i].clear(); qe[i].clear();
    	}
    	printf("%d",ans);
    }
    

    2161: 布娃娃

    (c)离散化,把(l,r,p)分别排序
    1-n循环p把该加的c[l]加上,该减的c[r]减掉,权值线段树查第k大即可
    看错第k大调了好久QAQ


    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define LL long long 
    #define M 19921228
    #define update(now) d[now]=d[now*2]+d[now*2+1] 
    using namespace std;
    
    int i,m,n,j,k,a[1000001],padd,pfirst,pmod,pprod,cadd,cfirst,cmod,cprod,ladd,lfirst,lmod,lprod,radd,rfirst,rmod,rprod,d[1000001],z[1000001],ans,topl=1,topr=1,pre[1000001],c[1000001];
    
    struct vv
    {
    	int z, w;
    } l[200000],r[200001],p[200001];
    bool cmp(vv a,vv b){ return a.z<b.z; }
    
    void modify(int now,int l,int r,int w,int z)
    {
    	if(l==r) {d[now]+=z; return;}
    	int mid=(l+r)>>1;
    	if(w<=mid) modify(now*2,l,mid,w,z);
    	else modify(now*2+1,mid+1,r,w,z);
    	update(now);
    }
    
    int ask(int now,int l,int r,int w)
    {
    	if(l==r) return l;
    	if(k<=0) return 0;
    	if(d[now]<w) return 0;
    	int mid=(l+r)>>1;
    	if(d[now*2+1]>=w) return ask(now*2+1,mid+1,r,w);
    	return ask(now*2,l,mid,w-d[now*2+1]);
    }
    
    int main()
    {
    	scanf("%d",&n);
    	scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",&padd,&pfirst,&pmod,&pprod,&cadd,&cfirst,&cmod,&cprod,&ladd,&lfirst,&lmod,&lprod,&radd,&rfirst,&rmod,&rprod);
    	l[1].z=lfirst%lmod; r[1].z=rfirst%rmod;
    	p[1].z=pfirst%pmod; c[1]=cfirst%cmod;
    	z[1]=c[1];
    	l[1].w=r[1].w=p[1].w=1;
    	for(i=2;i<=n;i++)
    	{
    		l[i].z=((LL)l[i-1].z*lprod%lmod+ladd+i)%lmod;
    		r[i].z=((LL)r[i-1].z*rprod%rmod+radd+i)%rmod;
    		p[i].z=((LL)p[i-1].z*pprod%pmod+padd+i)%pmod;
    		c[i]=((LL)c[i-1]*cprod%cmod+cadd+i)%cmod;
    		z[i]=c[i];
    		l[i].w=r[i].w=p[i].w=i;
    	}
    	sort(z+1,z+1+n);
    	m=unique(z+1,z+1+n)-z-1;
    	for(int i=1;i<=n;i++)
    	{ 
    		k=lower_bound(z+1,z+1+m,c[i])-z; pre[k]=c[i]; c[i]=k;
    		if(l[i].z>r[i].z) swap(l[i].z,r[i].z);
    	}
    	l[n+1].z=r[n+1].z=0x3f3f3f3f;
    	sort(l+1,l+1+n,cmp);  sort(r+1,r+1+n,cmp); sort(p+1,p+1+n,cmp);
    	for(i=1;i<=n;i++)
    	{
    		int k=p[i].z;
    		while(l[topl].z<=k) modify(1,1,n,c[l[topl].w],1), topl+=1;
    		while(r[topr].z<k) modify(1,1,n,c[r[topr].w],-1), topr+=1;
    		ans=(ans+pre[ask(1,1,n,p[i].w)])%M;
    	}
    	printf("%d",ans);
    }
    

    1818: [Cqoi2010]内部白点

    易发现所有能变色的白点一定在第一秒就能变色,上下左右都有黑点。而且永不停止是不可能的。

    把黑点离散化,按y排一下序,用vector在每一列的上端点存1,下端点存-1到每一行,顺便找出每一行的左端点和右端点用数组存下来

    最后按行扫一遍,先加上端点再区间查询这一行的左右段点再减下端点即可


        #include<iostream>
        #include<cstdio>
        #include<algorithm>
        #include<vector>
        #include<cstring>
        using namespace std;
        
        int i,m,n,j,k,zl[100001],zr[100001],x,y,l,r,ll[100001],rr[100001],c[100001],ans;
        
        struct vv{	int x,y; } a[100001],b[100001];
        
        vector <pair<int,int> > q[100001], p[100001];
        
        bool cmp2(vv a,vv b) {if(a.y==b.y) return a.x<b.x; return a.y<b.y;}
        
        void add(int now,int z) { for(int i=now;i<=y;i+=i & -i) c[i]+=z;}
        
        int ask(int now)
        {
        	int ans=0;
        	for(int i=now;i>0;i-=i & -i) ans+=c[i];
        	return ans; 
        }
        
        int main()
        {
        	scanf("%d",&n);
        	for(i=1;i<=n;i++) 
        	{
        		scanf("%d%d",&a[i].x,&a[i].y);
        		zl[i]=a[i].x; zr[i]=a[i].y;
        	}
        	sort(zl+1,zl+1+n);	sort(zr+1,zr+1+n);
        	x=unique(zl+1,zl+1+n)-zl-1; y=unique(zr+1,zr+1+n)-zr-1;
        	
        	for(i=1;i<=n;i++)
        	{
        		a[i].x=lower_bound(zl+1,zl+1+x,a[i].x)-zl, a[i].y=lower_bound(zr+1,zr+1+y,a[i].y)-zr;
        		b[i].x=a[i].x; b[i].y=a[i].y;
        	}
        	sort(a+1,a+1+n,cmp2);
        	l=0x3f3f3f3f; r=0;
        	memset(ll,0x3f,sizeof(ll));
        	for(i=1;i<=n;i++)
        	{
        		if(a[i].y!=a[i-1].y)
        		{
        			if(r) p[r].push_back(make_pair(a[i-1].y,-1)), q[l].push_back(make_pair(a[i-1].y,1));
        			l=0x3f3f3f3f; r=0;
        		}  
        		l=min(a[i].x,l); r=max(a[i].x,r);
        		ll[a[i].x]=min(ll[a[i].x],a[i].y);
        		rr[a[i].x]=max(rr[a[i].x],a[i].y);
        	}
        	if(r) p[r].push_back(make_pair(a[n].y,-1)), q[l].push_back(make_pair(a[n].y,1));
        
        	for(i=1;i<=x;i++) 
        	{
        		for(j=0;j<q[i].size();j++) add(q[i][j].first,q[i][j].second);
        		if(rr[i])	ans+=ask(rr[i])-ask(ll[i]-1);
        		for(j=0;j<p[i].size();j++) add(p[i][j].first,p[i][j].second);
        	}
        	printf("%d",ans);
        }
    
  • 相关阅读:
    刻舟求剑,
    录制时间是不准确的,
    HIV T2
    DNA RNA
    洛谷 P1428 小鱼比可爱
    Codevs 1081 线段树练习2
    Codevs 1080 线段树联系
    Tarjan算法
    Codevs 2611 观光旅游
    洛谷 1865 A%B问题
  • 原文地址:https://www.cnblogs.com/ZUTTER/p/10505708.html
Copyright © 2011-2022 走看看