zoukankan      html  css  js  c++  java
  • Mail.Ru Cup 2018 Round 2

      A:阅读理解。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 1010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,m,a[N],b[N];
    signed main()
    {
    /*#ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	const char LL[]="%I64d
    ";
    #endif*/
    	n=read(),m=read();
    	for (int i=1;i<=n;i++) a[i]=read();
    	for (int i=1;i<=n;i++) b[i]=read();
    	if (a[1])
    	{
    		if (a[m]) {cout<<"YES";return 0;}
    		if (b[m])
    		{
    			for (int i=m+1;i<=n;i++)
    			if (a[i]&&b[i]) {cout<<"YES";return 0;}
    		}
    	}
    	cout<<"NO";
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      B:即维护一个01序列有多少段1,瞎算算即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 100010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,m,k,ans;
    ll a[N];
    signed main()
    {
    /*#ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	const char LL[]="%I64d
    ";
    #endif*/
    	n=read(),m=read(),k=read();
    	for (int i=1;i<=n;i++) a[i]=read()-k;
    	for (int i=1;i<=n;i++)
    	if (a[i]>0&&a[i-1]<=0) ans++;
    	for (int i=1;i<=m;i++)
    	{
    		int op=read();
    		if (op==0)
    		{
    			printf("%d
    ",ans);
    		}
    		else
    		{
    			int x=read(),y=read();
    			if (a[x]<=0)
    			{
    				a[x]+=y;
    				if (a[x]>0) ans++,ans-=a[x-1]>0,ans-=a[x+1]>0;
    			}
    		}
    	}
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      C:任取两人各一段连续+区间,容易发现起始位置之差在模gcd(ta,tb)意义下总是相同的。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int l1,r1,t1,l2,r2,t2;
    ll cross(ll l1,ll r1,ll l2,ll r2)
    {
    	if (l1>l2) swap(l1,l2),swap(r1,r2);
    	return max(min(r2,r1)-l2+1,0ll);
    }
    signed main()
    {
    /*#ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	const char LL[]="%I64d
    ";
    #endif*/
    	l1=read(),r1=read(),t1=read(),l2=read(),r2=read(),t2=read();
    	int x=gcd(t1,t2);
    	ll ans=cross(l1,r1,l2,r2);
    	int u=(l2-l1)/x;
    	ans=max(ans,cross(l1,r1,l2-1ll*u*x,r2-1ll*u*x));
    	u--;
    	ans=max(ans,cross(l1,r1,l2-1ll*u*x,r2-1ll*u*x));
    	u++,u++;
    	ans=max(ans,cross(l1,r1,l2-1ll*u*x,r2-1ll*u*x));
    	cout<<ans;
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      D:一个比较坑的题。容易想到随便找一个需要改的字符串,对其最短修改串(即去掉前后缀极长不需修改的部分)进行修改,判一下是否对其它串也合法就做完了。但问题是这样并不一定最优,可能需要延长修改部分,达到避免对某些串修改的目的,如ac→bc a→a,不应选a→b而应选ac→bc。于是考虑先把所有不需要改的串去掉,需要改的串求出最短修改串,如果任意一对最短修改串不同即无解。否则由每个最短修改串尽量往两边延伸,得到合法的极长修改串,再对其进行检验即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 3010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,u,nxt[N],L[N],R[N],len[N];
    char a[N][N],b[N][N],anss[N],anst[N];
    bool flag[N];
    signed main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	const char LL[]="%I64d
    ";
    #endif
    	n=read();
    	for (int i=1;i<=n;i++) scanf("%s",a[i]+1);
    	for (int i=1;i<=n;i++) scanf("%s",b[i]+1);
    	for (int i=1;i<=n;i++)
    	{
    		int m=strlen(a[i]+1);len[i]=m;
    		flag[i]=1;
    		for (int j=1;j<=m;j++)
    		if (a[i][j]!=b[i][j]) {flag[i]=0;break;}
    		if (!flag[i])
    		{
    			int t;
    			for (int k=1;k<=m;k++)
    			if (a[i][k]!=b[i][k])
    			{
    				t=m;
    				while (a[i][t]==b[i][t]) t--;
    				L[i]=k,R[i]=t;
    				if (!u) u=t-k+1;else if (t-k+1!=u) {cout<<"NO";return 0;}
    				break;
    			}
    		}
    	}
    	int l=0,r=0;
    	for (int i=1;i<=3001;i++)
    	{
    		bool f=0;
    		for (int j=1;j<=n;j++)
    		if (!flag[j]&&L[j]==i) {f=1;break;}
    		if (f) {l=i-1;break;}
    		char c;
    		for (int j=1;j<=n;j++)
    		if (!flag[j]) {c=a[j][L[j]-i];break;}
    		for (int j=1;j<=n;j++)
    		if (!flag[j]) if (c!=a[j][L[j]-i]) {f=1;break;}
    		if (f) {l=i-1;break;}
    	}
    	for (int i=1;i<=3001;i++)
    	{
    		bool f=0;
    		for (int j=1;j<=n;j++)
    		if (!flag[j]&&R[j]+i>len[j]) {f=1;break;}
    		if (f) {r=i-1;break;}
    		char c;
    		for (int j=1;j<=n;j++)
    		if (!flag[j]) {c=a[j][R[j]+i];break;}
    		for (int j=1;j<=n;j++)
    		if (!flag[j]) if (c!=a[j][R[j]+i]) {f=1;break;}
    		if (f) {r=i-1;break;}
    	}
    	for (int i=1;i<=n;i++)
    	if (!flag[i])
    	{
    		int v=L[i]-l;u+=l+r;
    		for (int j=1;j<=u;j++) anss[j]=a[i][v+j-1],anst[j]=b[i][v+j-1];
    		break;
    	}
    	nxt[0]=-1;
    	for (int i=1;i<=u;i++)
    	{
    		int j=nxt[i-1];
    		while (~j&&anss[j+1]!=anss[i]) j=nxt[j];
    		nxt[i]=j+1;
    	}
    	for (int i=1;i<=n;i++)
    	{
    		int cur=0,m=len[i];
    		for (int j=1;j<=m;j++)
    		{
    			while (~cur&&a[i][j]!=anss[cur+1]) cur=nxt[cur];
    			cur++;
    			if (cur==u)
    			{
    				for (int k=j-u+1;k<=j;k++) a[i][k]=anst[k-(j-u+1)+1];
    				break;
    			}
    		}
    		for (int j=1;j<=m;j++)
    		if (a[i][j]!=b[i][j]) {cout<<"NO";return 0;}
    	}
    	cout<<"YES"<<endl;
    	printf("%s
    ",anss+1);printf("%s
    ",anst+1);
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      E:显然二分答案转换成01序列上的问题,然后问题就变为是否能从s个区间中选m个使其并区间的数字和>=k。显然可以合并掉有包含关系的区间后dp,具体地,设f[i][j]为前i个区间选j个时最多能有多少个1,考虑上个区间与当前区间是否有交,分两种情况转移,没有交直接取最大值,有交的情况用堆(或者单调队列?反正cf跑得快)维护。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define ll long long
    #define N 1510
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,m,s,k,a[N],c[N],f[N][N],ans=-1;
    bool flag[N];
    struct data
    {
    	int x,y;
    	bool operator <(const data&a) const
    	{
    		return x<a.x||x==a.x&&y<a.y;
    	}
    	bool operator ==(const data&a) const
    	{
    		return x==a.x&&y==a.y;
    	}
    }b[N],d[N];
    priority_queue<int> ins,del;
    bool check(int u)
    {
    	for (int i=1;i<=n;i++)
    	if (a[i]<=u) c[i]=1;else c[i]=0;
    	for (int i=1;i<=n;i++) c[i]+=c[i-1];
    	memset(f,0,sizeof(f));
    	for (int j=1;j<=s;j++)
    	{
    		int x=0,t=0;
    		while (!ins.empty()) ins.pop();
    		while (!del.empty()) del.pop();
    		for (int i=1;i<=m;i++)
    		{
    			while (x<i&&b[x+1].y<b[i].x) x++,del.push(f[x][j-1]-c[b[x].y]),t=max(t,f[x][j-1]);
    			while (!del.empty()&&ins.top()==del.top()) ins.pop(),del.pop();
    			f[i][j]=max(t+c[b[i].y]-c[b[i].x-1],c[b[i].y]+(ins.empty()?-1000000:ins.top()));
    			ins.push(f[i][j-1]-c[b[i].y]);
    		}
    	}
    	for (int i=1;i<=m;i++) if (f[i][s]>=k) return 1;
    	return 0;
    }
    signed main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	const char LL[]="%I64d
    ";
    #endif
    	n=read(),m=read(),s=read(),k=read();
    	for (int i=1;i<=n;i++) a[i]=read();
    	for (int i=1;i<=m;i++) b[i].x=read(),b[i].y=read();
    	sort(b+1,b+m+1);
    	m=unique(b+1,b+m+1)-b-1;
    	for (int i=1;i<=m;i++)
    		for (int j=1;j<=m;j++)
    		if (i!=j&&b[j].x<=b[i].x&&b[j].y>=b[i].y) {flag[i]=1;break;}
    	int t=0;
    	for (int i=1;i<=m;i++)
    	if (!flag[i]) d[++t]=b[i];
    	m=t;s=min(s,m);
    	for (int i=1;i<=m;i++) b[i]=d[i];
    	sort(b+1,b+m+1);
    	int l=1,r=1000000000;
    	while (l<=r)
    	{
    		int mid=l+r>>1;
    		if (check(mid)) ans=mid,r=mid-1;
    		else l=mid+1;
    	}
    	cout<<ans;
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      F:冷静一下可以发现,由异或的消去性,这个题和树没有任何关系,求出每个点到根的路径的异或和后,就变为一堆数的问题。容易想到的做法是建一棵trie,二分答案,对每个数trie上跑一遍。时间复杂度O(nlog2v),空间复杂度O(nlogv),都炸掉了。

      先考虑优化时间复杂度。trie还是要建的,改为按位考虑。对于当前位是否填1,记录所有需要考虑的对(即异或后与已确定位完全相同),算出下一位均填0和均填1的方案数(即异或的下一位填0),与k进行比较确定答案,如果填1就将k减掉该方案数。然后给每个对拓展下一位。注意到考虑第i位时,所有对都处于trie的第i层,并且每个点只会被考虑两次,所以时间复杂度O(nlogv)。

      然后考虑将空间复杂度优化至线性。将所有数排序,就得到了所谓的隐式trie,因为排序后的一段区间就对应了trie上的一棵子树。跑同样的做法即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define ll long long
    #define N 1000010
    ll read()
    {
    	ll x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,p[N],t,cnt,tot;
    ll m,ans,a[N],b[N][2],c[N][2];
    struct data{int to,nxt;ll len;
    }edge[N];
    void addedge(int x,int y,ll z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
    void dfs(int k)
    {
    	for (int i=p[k];i;i=edge[i].nxt)
    	{
    		a[edge[i].to]=a[k]^edge[i].len;
    		dfs(edge[i].to);
    	}
    }
    int jump(int x,int u,int k)
    {
    	if (u==0) return ((a[x]>>k)&1)==0?x:-1;
    	for (int i=x;i<=n;i++)
    	{
    		if ((a[i]>>k+1)!=(a[x]>>k+1)) return -1;
    		if ((a[i]>>k)&1) return i;
    	}
    	return -1;
    }
    int query(int x,int u,int k)
    {
    	x=jump(x,u,k);
    	if (x==-1) return 0;
    	for (int i=x+1;i<=n;i++)
    	if ((a[i]>>k)!=(a[x]>>k)) return i-x;
    	return n-x+1;
    }
    signed main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	const char LL[]="%I64d
    ";
    #endif
    	n=read(),m=read();
    	for (int i=2;i<=n;i++)
    	{
    		int x=read();ll y=read();
    		addedge(x,i,y);
    	}
    	dfs(1);sort(a+1,a+n+1);cnt++;b[cnt][0]=b[cnt][1]=1;
    	for (int k=62;~k;k--)
    	{
    		ll s=0;
    		for (int i=1;i<=cnt;i++)
    		s+=1ll*query(b[i][0],0,k)*query(b[i][1],0,k)+1ll*query(b[i][0],1,k)*query(b[i][1],1,k);
    		tot=0;ans<<=1;
    		if (s>=m)
    		{
    			for (int i=1;i<=cnt;i++)
    			{
    				if (query(b[i][0],0,k)&&query(b[i][1],0,k)) tot++,c[tot][0]=jump(b[i][0],0,k),c[tot][1]=jump(b[i][1],0,k);
    				if (query(b[i][0],1,k)&&query(b[i][1],1,k)) tot++,c[tot][0]=jump(b[i][0],1,k),c[tot][1]=jump(b[i][1],1,k);
    			}
    		}
    		else
    		{
    			for (int i=1;i<=cnt;i++)
    			{
    				if (query(b[i][0],0,k)&&query(b[i][1],1,k)) tot++,c[tot][0]=jump(b[i][0],0,k),c[tot][1]=jump(b[i][1],1,k);
    				if (query(b[i][0],1,k)&&query(b[i][1],0,k)) tot++,c[tot][0]=jump(b[i][0],1,k),c[tot][1]=jump(b[i][1],0,k);
    			}
    			m-=s;ans++;
    		}
    		cnt=tot;
    		for (int i=1;i<=cnt;i++) b[i][0]=c[i][0],b[i][1]=c[i][1];
    	}
    	cout<<ans;
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      G:先考虑怎么求答案是否为0。平面图上下连通相当于对偶图左右不连通,考虑以凸多边形某个点标记Bob,那么每个圆会给该点带来一个形如圆角凸多边形的不合法区域,不合法区域有交则称两圆连通,如果这些不合法区域使得左右连通,说明答案>0。回到原题,做法类似,对圆之间的连通关系(及圆和边界的连通关系)建图后,即求最小割点数量,拆点跑最小割即可。

      主要问题在于如何判断圆角凸多边形是否有交。真要带上圆角简直不可做,事实上可以转化为求两凸多边形的最近距离。对任一凸包取反后求闵可夫斯基和,看所得凸包中是否存在点到原点的距离<两圆半径之和即可。这得讨论一下原点是否在凸包中。然后我就因为这个写挂调了几天。自闭了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cassert>
    using namespace std;
    #define ll long long
    #define int long long
    #define N 410
    #define S 0
    #define T 401
    #define in(i) (i*2-1)
    #define out(i) (i*2)
    #define vector point
    #define p(x,y) (point){x,y}
    #define O p(0,0)
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,m,w,L,R,p[N],d[N],q[N],cur[N],t=-1,ans;
    struct point
    {
    	int x,y;
    	vector operator +(const vector&a) const
    	{
    		return (vector){x+a.x,y+a.y};
    	}
    	vector operator -(const vector&a) const
    	{
    		return (vector){x-a.x,y-a.y};
    	}
    	int operator *(const vector&a) const
    	{
    		return x*a.y-y*a.x;
    	}
    	int operator ^(const vector&a) const
    	{
    		return x*a.x+y*a.y;
    	}
    }a[N],u[N<<1],v[N<<1],r[N<<1],Left;
    struct circle{point o;int r;
    }b[N];
    struct data{int to,nxt,cap,flow;
    }edge[N*N<<3];
    void addedge(int x,int y,int z)
    {
    	t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=z,p[x]=t;
    	t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=0,p[y]=t;
    }
    bool bfs()
    {
    	memset(d,255,sizeof(d));d[S]=0;
    	int head=0,tail=1;q[1]=S;
    	do
    	{
    		int x=q[++head];
    		for (int i=p[x];~i;i=edge[i].nxt)
    		if (d[edge[i].to]==-1&&edge[i].flow<edge[i].cap)
    		{
    			d[edge[i].to]=d[x]+1;
    			q[++tail]=edge[i].to;
    		}
    	}while (head<tail);
    	return ~d[T];
    }
    int work(int k,int f)
    {
    	if (k==T) return f;
    	int used=0;
    	for (int i=cur[k];~i;i=edge[i].nxt)
    	if (d[k]+1==d[edge[i].to])
    	{
    		int w=work(edge[i].to,min(f-used,edge[i].cap-edge[i].flow));
    		edge[i].flow+=w,edge[i^1].flow-=w;
    		if (edge[i].flow<edge[i].cap) cur[k]=i;
    		used+=w;if (used==f) return f;
    	}
    	if (used==0) d[k]=-1;
    	return used;
    }
    void dinic()
    {
    	while (bfs())
    	{
    		memcpy(cur,p,sizeof(p));
    		ans+=work(S,N);
    	}
    }
    int len(vector a){return a^a;}
    bool isin(point *r,int n) 
    {
    	for (int i=2;i<=n;i++)
    	if ((r[i]-r[i-1])*(O-r[i-1])<0) return 0;
    	return 1;
    }
    bool check(point a,point b,int r)
    {
    	if (((b-a)^(O-a))>0&&((a-b)^(O-b))>0)
    	return ((b-a)*(O-a))*((b-a)*(O-a))<r*r*len(a-b);
    	else return 0;
    }
    int merge(point *u,point *v)
    {
    	r[1]=u[1]+v[1];int tail=1;
    	int i=1,j=1;
    	while (i<=n||j<=n)
    	{
    		if (i>n) j++;
    		else if (j>n) i++;
    		else if ((u[i]+v[j+1]-r[tail])*(u[i+1]+v[j]-r[tail])>0) j++;
    		else i++;
    		point t=u[i]+v[j];
    		while (tail>1&&(t-r[tail-1])*(r[tail]-r[tail-1])>0) tail--;
    		r[++tail]=t;
    	}
    	return tail;
    }
    bool cross(circle x,circle y)
    {
    	for (int i=1;i<=n;i++) u[i]=x.o-(a[i]-Left);
    	for (int i=1;i<=n;i++) v[i]=(a[i]-Left)-y.o;
    	int u_first=1;
    	for (int i=2;i<=n;i++) if (u[i].x<u[u_first].x||u[i].x==u[u_first].x&&u[i].y<u[u_first].y) u_first=i;
    	int v_first=1;
    	for (int i=2;i<=n;i++) if (v[i].x<v[v_first].x||v[i].x==v[v_first].x&&v[i].y<v[v_first].y) v_first=i;
    	for (int i=n+1;i<=2*n;i++) u[i]=u[i-n],v[i]=v[i-n];
    	int tail=merge(u+u_first-1,v+v_first-1);
    	if (isin(r,tail)) return 1;
    	for (int i=1;i<=tail;i++)
    	if (len(r[i])<(x.r+y.r)*(x.r+y.r)) return 1;
    	for (int i=1;i<tail;i++)
    	if (check(r[i],r[i+1],x.r+y.r)) return 1;
    	return 0;
    }
    signed main()
    {                       
    #ifndef ONLINE_JUDGE
    	freopen("g.in","r",stdin);
    	freopen("g.out","w",stdout);
    	const char LL[]="%I64d
    ";
    #endif
    	n=read(),w=read();memset(p,255,sizeof(p));
    	Left=(point){N*N,N*N};L=N*N;R=-N*N;
    	for (int i=1;i<=n;i++)
    	{
    		a[i].x=read(),a[i].y=read();
    		L=min(L,a[i].x),R=max(R,a[i].x);
    		if (a[i].x<Left.x) Left=a[i];
    	}
    	m=read();
    	for (int i=1;i<=m;i++) b[i].o.x=read(),b[i].o.y=read(),b[i].r=read();
    	for (int i=1;i<=m;i++)
    		for (int j=i+1;j<=m;j++)
    		if (cross(b[i],b[j])) addedge(out(i),in(j),1),addedge(out(j),in(i),1);
    	for (int i=1;i<=m;i++)
    	{
    		if (b[i].o.x-(R-L)-b[i].r<0) addedge(S,in(i),1);
    		if (b[i].o.x+(R-L)+b[i].r>w) addedge(out(i),T,1);
    	}
    	for (int i=1;i<=m;i++) addedge(in(i),out(i),1);
    	dinic();
    	cout<<ans;
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
  • 相关阅读:
    又搬回来了233
    2017.10.2解题报告
    2017.10.1解题报告
    Android 百度地图开发(二)--- 定位功能之MyLocationOverlay,PopupOverlay的使用
    Last_IO_Errno: 1236 Last_IO_Error: Got fatal error 1236 from master when reading data from binary lo
    [Warning] Aborted connection 11203 to db: 'ide' user: 'nuc' host: 'prd01.mb.com' (Got an error writi
    浅析地方门户网优化的方法
    xxx==null和xxx.equals(null)的区别
    Java+7入门经典
    《UNIX环境高级编程》笔记--read函数,write函数,lseek函数
  • 原文地址:https://www.cnblogs.com/Gloid/p/10359881.html
Copyright © 2011-2022 走看看