zoukankan      html  css  js  c++  java
  • arc101F

    题目大意

    题解

    一开始想枚举每段的分界再判断,然而不好搞

    实际上把每个点到两边的距离设为(x,y),类似https://www.cnblogs.com/gmh77/p/12813589.html,变为用一条折线把所有点分成两个集合

    直接dp折线,转移时要么继承上一行位置,要么转移到前面的某个点,线段树维护

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define add(a,b) a=((a)+(b))%1000000007
    #define mod 1000000007
    #define N 1000000000
    #define ll long long
    //#define file
    using namespace std;
    
    struct type{int x,tp;} a[200001];
    struct Type{int x,y;} b[200001];
    int tr[7000001][2],X[200001],Y[200001],tot,n,m,i,j,k,l,len;
    ll Tr[7000001],ans,s;
    
    bool cmp(type a,type b) {return a.x<b.x;}
    bool Cmp(Type a,Type b) {return a.x<b.x || a.x==b.x && a.y>b.y;}
    
    void New(int t,int x) {if (!tr[t][x]) tr[t][x]=++len;}
    void change(int t,int l,int r,int x,ll s)
    {
    	int mid=(l+r)/2;
    	add(Tr[t],s);
    	if (l==r) return;
    	
    	if (x<=mid) New(t,0),change(tr[t][0],l,mid,x,s);
    	else New(t,1),change(tr[t][1],mid+1,r,x,s);
    }
    ll find(int t,int l,int r,int x,int y)
    {
    	int mid=(l+r)/2;
    	ll ans=0;
    	if (x<=l && r<=y) return Tr[t];
    	
    	if (x<=mid && tr[t][0]) add(ans,find(tr[t][0],l,mid,x,y));
    	if (mid<y && tr[t][1]) add(ans,find(tr[t][1],mid+1,r,x,y));
    	return ans;
    }
    
    int main()
    {
    	#ifdef file
    	freopen("arc101f.in","r",stdin);
    	#endif
    	
    	scanf("%d%d",&n,&m);
    	fo(i,1,n) scanf("%d",&j),a[++tot]={j,0};
    	fo(i,1,m) scanf("%d",&j),a[++tot]={j,1};
    	
    	sort(a+1,a+tot+1,cmp);
    	l=0;
    	fo(i,1,tot)
    	if (a[i].tp)
    	l=a[i].x; else X[i]=l?(a[i].x-l):0;
    	l=0;
    	fd(i,tot,1)
    	if (a[i].tp)
    	l=a[i].x; else Y[i]=l?(l-a[i].x):0;
    	
    	l=0;
    	fo(i,1,tot) if (X[i] && Y[i]) b[++l]={X[i],Y[i]};
    	tot=l;
    	sort(b+1,b+tot+1,Cmp);
    	l=0;
    	fo(i,1,tot) if (b[i].x!=b[i-1].x || b[i].y!=b[i-1].y) b[++l]=b[i];
    	tot=l;
    	
    	len=1;
    	change(1,1,N,N,1);
    	fd(i,tot,1)
    	{
    		s=find(1,1,N,b[i].y,N);
    		if (b[i].y==1) add(ans,s);
    		else change(1,1,N,b[i].y-1,s);
    	}
    	add(ans,Tr[1]);
    	printf("%lld
    ",ans);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Android PopupWindow 弹窗背景半透明,设置最大高度
    Android性能优化之:ViewStub
    EventBus使用详解(一)——初步使用EventBus
    Android开发中,那些让你相见恨晚的方法、类或接口
    android 提高进程优先级 拍照永不崩溃(闪退)
    Android框架 加载图片 库 Picasso 的使用简介
    vc 取windows系统信息 版本 cpu信息 内存信息 ie版本信息 office版本
    VC 三点 划 曲线
    VC 类泡泡龙游戏算法
    vc 判断哪个按键 被按下 消息 按键 状态
  • 原文地址:https://www.cnblogs.com/gmh77/p/13642164.html
Copyright © 2011-2022 走看看