1. 程式人生 > >ACM-ICPC國際大學生程式設計競賽北京賽區(2017)網路賽(A+E+F+G+I)

ACM-ICPC國際大學生程式設計競賽北京賽區(2017)網路賽(A+E+F+G+I)

目錄

A - Visiting Peking University(模擬)

E - Territorial Dispute(數學幾何+思維)

F - Cake(思維)

G - Bounce(找規律)

I - Minimum(線段樹模板題)


A - Visiting Peking University(模擬)

Ming is going to travel for n days and the date of these days can be represented by n integers: 0, 1, 2, …, n-1. He plans to spend m consecutive days(2 ≤ m ≤ n)in Beijing. During these m days, he intends to use the first day and another day to visit Peking university. Before he made his plan, Ming investigated on the number of tourists who would be waiting in line to enter Peking university during his n-day trip, and the results could be represented by an integer sequence p[i] (0 ≤ i ≤ n-1, p[i] represents the number of waiting tourists on day i). To save time, he hopes to choose two certain dates a and b to visit PKU(0 ≤ a < b ≤ n-1), which makes p[a] + p[b] as small as possible.

Unfortunately, Ming comes to know that traffic control will be taking place in Beijing on some days during his n-day trip, and he won’t be able to visit any place in Beijing, including PKU, on a traffic control day. Ming loves Beijing and he wants to make sure that m days can be used to visit interesting places in Beijing. So Ming made a decision:  spending k (m ≤ k ≤ n) consecutive days in Beijing is also acceptable if there are k - m traffic control days among those k days. Under this complicated situation, he doesn’t know how to make the best schedule. Please write a program to help Ming determine the best dates of the two days to visit Peking University.  Data guarantees a unique solution.

Input

There are no more than 20 test cases.

For each test case:

The first line contains two integers, above mentioned n and m (2 ≤ n ≤ 100, 2 ≤ m ≤ n).

The second line contains n integers, above mentioned p[0] , p[1] , … p[n-1]. (0 ≤ p[i] ≤ 1000, i = 0 ... n-1)

The third line is an integer q (0 ≤ q ≤ n), representing the total number of traffic control days during the n-day trip, followed by q integers representing the dates of these days.

Output

One line, including two integers a and b, representing the best dates for visiting PKU.

Sample Input

7 3
6 9 10 1 0 8 35
3 5 6 2
4 2
10 11 1 2
1 2

Sample Output

0 3
1 3

【分析】模擬題。出差n天,要拿出連續的m天出去玩,其中這m天的第一天和另一天要去北京大學。這m天中會有一些時間是交通管制日,在交通管制日是不能出去的,給出每天出去要等的每天的權值p[i],使得這兩天出去p之和最小。 第一個例子是0  3 而不是3  4 是因為  如果是3  4的話,他只能玩兩天,但是要玩3天的,所以選的是0  3。還要注意下標從0開始。

【程式碼】

#include<bits/stdc++.h>
using namespace std;

const int maxn=1010;
int p[maxn];
int vis[maxn];

int main()
{
	int n,m,a,b;
	while(~scanf("%d%d",&n,&m))
	{
		memset(vis,0,sizeof(vis));
		memset(p,0,sizeof(p));
		for(int i=0;i<n;i++)scanf("%d",&p[i]);
		int q;scanf("%d",&q);
		while(q--)
		{
			int x;scanf("%d",&x);
			vis[x]=1;
		}
		int minn=5000,k=1,t=-1;
		for(int i=0;i<n;i++)
		{
			k=1;
			if(vis[i])continue;
			int aa=p[i],bb=2000;
			for(int j=i+1;j<n;j++)
			{
				
				if(vis[j])continue;
				if(bb>p[j])
				{
					//cout<<"i="<<i<<",j="<<j<<endl;
					bb=p[j];//cout<<"bb="<<bb<<endl;
					t=j;
				}
				k++;//cout<<"k="<<k<<endl;
				if(k==m)break;
			}
			if(k<m)continue;
			if(minn>aa+bb)
			{
			//	cout<<aa<<","<<bb<<endl;
				minn=aa+bb;
				a=i;b=t;
			}
		}
		printf("%d %d\n",a,b);
	}
	return 0;
}

E - Territorial Dispute(數學幾何+思維)

In 2333, the C++ Empire and the Java Republic become the most powerful country in the world. They compete with each other in the colonizing the Mars.

There are n colonies on the Mars, numbered from 1 to n. The i-th colony's location is given by a pair of integers (xi, yi). Notice that latest technology in 2333 finds out that the surface of Mars is a two-dimensional plane, and each colony can be regarded as a point on this plane. Each colony will be allocated to one of the two countries during the Mars Development Summit which will be held in the next month.

After all colonies are allocated, two countries must decide a border line. The Mars Development Convention of 2048 had declared that: A valid border line of two countries should be a straight line, which makes colonies of different countries be situated on different sides of the line.

The evil Python programmer, David, notices that there may exist a plan of allocating colonies, which makes the valid border line do not exist. According to human history, this will cause a territorial dispute, and eventually lead to war.

David wants to change the colony allocation plan secretly during the Mars Development Summit. Now he needs you to give him a specific plan of allocation which will cause a territorial dispute. He promises that he will give you 1000000007 bitcoins for the plan.

Input

The first line of the input is an integer T, the number of the test cases (T ≤ 50).

For each test case, the first line contains one integer n (1 ≤ n ≤ 100), the number of colonies.

Then n lines follow. Each line contains two integers xi, yi (0 ≤ xi, yi ≤ 1000), meaning the location of the i-th colony. There are no two colonies share the same location.

There are no more than 10 test cases with n > 10.

Output

For each test case, if there exists a plan of allocation meet David's demand, print "YES" (without quotation) in the first line, and in the next line, print a string consisting of English letters "A" and "B". The i-th character is "A" indicates that the i-th colony was allocated to C++ Empire, and "B" indicates the Java Republic.

If there are several possible solutions, you could print just one of them.

If there is no solution, print "NO".

Sample Input

2
2
0 0
0 1
4
0 0
0 1
1 0
1 1

Sample Output

NO
YES
ABBA

【分析】n≤2時,顯然是NO;n=3時,其中一點在兩點的連線中間是YES,否則是NO;n≥4時,因為n=4時是可以變成YES的,分兩種情況,當點在另外3個點圍成的三角形內部或兩邊相交,是YES,否則是NO。把這四個輸出,剩下的隨便輸出就好了。

【程式碼】https://blog.csdn.net/axuhongbo/article/details/78074968 

#include<bits/stdc++.h>
using namespace std;

const double eps=1e-8;
double x[110],y[110];

struct point
{
    double x,y;
};
struct line
{
    point s,e;
};

int sgn(double x)
{
    if(fabs(x)<eps)return 0;
    if(x<0)return -1;
    return 1;
}
double mul(point sp,point ep,point op)
{
    return ((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
bool inter(line u ,line v)
{
    return ((max(u.s.x,u.e.x)>=min(v.s.x,v.e.x))&&
            (max(v.s.x,v.e.x)>=min(u.s.x,u.e.x))&&
            (max(u.s.y,u.e.y)>=min(v.s.y,v.e.y))&&
            (max(v.s.y,v.e.y)>=min(u.s.y,u.e.y))&&
            (mul(v.s,u.e,u.s)*mul(u.e,v.e,u.s)>=0)&&
            (mul(u.s,v.e,v.s)*mul(v.e,u.e,v.s)>=0));
}
double dist(double x1,double y1,double x2,double y2)
{
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double mian(double x1,double y1,double x2,double y2,double x3,double y3)
{
    double d1,d2,d3,p;
    d1=dist(x1,y1,x2,y2);
    d2=dist(x2,y2,x3,y3);
    d3=dist(x1,y1,x3,y3);
    p=(d1+d2+d3)/2;
    return sqrt(p*(p-d1)*(p-d2)*(p-d3));
}

int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
    	int n;scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf",&x[i],&y[i]);
        }
        if(n<3){printf("NO\n");continue;}
        if(n==3)
        {
            if((y[1]-y[0])*(x[2]-x[0])==(x[1]-x[0])*(y[2]-y[0]))
            {
                printf("YES\n");
                double d0,d1,d2;
                d0=dist(x[1],y[1],x[2],y[2]);
                d1=dist(x[0],y[0],x[2],y[2]);
                d2=dist(x[1],y[1],x[0],y[0]);
                if(d0==d1+d2)printf("BAA\n");
                else if(d1==d0+d2)printf("ABA\n");
                else printf("AAB\n");
            }
            else printf("NO\n");
            continue;
        }
        if(n>=4)
        {
            printf("YES\n");
            if((y[1]-y[0])*(x[2]-x[0])==(x[1]-x[0])*(y[2]-y[0]))
            {
                double d0,d1,d2;
                d0=dist(x[1],y[1],x[2],y[2]);
                d1=dist(x[0],y[0],x[2],y[2]);
                d2=dist(x[1],y[1],x[0],y[0]);
                if(d0==d1+d2)printf("BAA");
                else if(d1==d0+d2)printf("ABA");
                else printf("AAB");
                for(int i=0;i<n-3;i++)printf("A");
                printf("\n");
            }
            else
            {
                double s0,s1,s2,s3;
                s3=mian(x[0],y[0],x[1],y[1],x[2],y[2]);
                s2=mian(x[0],y[0],x[1],y[1],x[3],y[3]);
                s1=mian(x[0],y[0],x[3],y[3],x[2],y[2]);
                s0=mian(x[3],y[3],x[1],y[1],x[2],y[2]);
                if(sgn(s0+s1+s2-s3)==0)printf("AAAB");
                else if(sgn(s0+s1-s2+s3)==0)printf("AABA");
                else if(sgn(s0-s1+s2+s3)==0)printf("ABAA");
                else if(sgn(s0-s1-s2-s3)==0)printf("ABBB");
                else
                {
                    point a,b,c,d;
                    a.x=x[0];
                    a.y=y[0];
                    b.x=x[1];
                    b.y=y[1];
                    c.x=x[2];
                    c.y=y[2];
                    d.x=x[3];
                    d.y=y[3];
                    line ab,ac,ad,bc,bd,cd;
                    ab.e=a;
                    ab.s=b;
                    ac.e=a;
                    ac.s=c;
                    ad.e=a;
                    ad.s=d;
                    bc.e=c;
                    bc.s=b;
                    bd.e=d;
                    bd.s=b;
                    cd.e=d;
                    cd.s=c;
                    if(inter(ab,cd))printf("AABB");
                    else if(inter(ac,bd))printf("ABAB");
                    else if(inter(ad,bc))printf("ABBA");
                }
                for(int i=0;i<n-4;i++)printf("A");
                printf("\n");
            }
        }
    }
}

F - Cake(思維)

To celebrate that WF-2018 will be held in PKU, Alice, Bob, and Cate are asked to make

N cakes.

Every cake i needs to go through 3 steps in restrict order:

1. Alice mixes flour and water for ai minutes;

2. Bob carefully bakes it for bi minutes;

3. Cate makes cream decoration for ci minutes.

Since Cate wants to have different kinds of cakes, the third step of any cake i is always not less time-consuming than the second step of any cake j. Also, it is reasonable that once anyone starts to process a cake, the procedure cannot be stopped then be resumed.

To have these cakes done as soon as possible, they need your help.

Input

There are several cases (less than 15 cases).

The first line of every case contains an integer N (1 ≤ N ≤ 105)—the number of cakes to prepare.

After that, N lines follow, each of them contains three integers ai, bi and ci (1 ≤ i ≤ N; 0 <ai, bi, ci < 106)—time that needs to be spent on the three steps of cake i respectively.

It is guaranteed that for any i and any j, bi is no greater than cj.

The input ends with N = 0.

Output

For every case, print in a single line the least possible time to make all cakes.

Sample Input

3
5 3 4
3 2 9
3 4 8
0

Sample Output

26

【題意】做一個蛋糕需要3個步驟,給出每個蛋糕的每個步驟需要的時間。規定第3個步驟用時不小於第2個步驟。且做蛋糕途中不可以有休息時間,要連續,不然就要重新做。求做完指定數目的蛋糕需要的最小時間。

【分析】是一道思維題吧,想清楚了就知道怎麼做了吧大概....然鵝我還咩有想清楚,感覺做蛋糕的步驟應該有先後的,但是這個程式碼只是對時間進行比較選擇,並沒有考慮到是不是前一個步驟已經處理完.....想不通....先掛一份程式碼.... 分工是下面這樣的~

程式碼:(戳這)

#include<bits/stdc++.h>
using namespace std;

#define INF 0x3f3f3f3f
#define maxn 1311000
typedef long long ll;
ll a[maxn],b[maxn],c[maxn];
 
int main()
{
    int n;
    while(scanf("%d",&n)&&n)
	{
        ll sum1=0,sum3=0;
        ll minab=INF,minbc=INF;
        for(int i=1;i<=n;i++)
		{
            scanf("%lld %lld %lld",&a[i],&b[i],&c[i]);
            
            sum1+=a[i];
            sum3+=c[i];
			
			if(minab>a[i]+b[i])minab=a[i]+b[i];
            if(minbc>b[i]+c[i])minbc=b[i]+c[i];
		}
        printf("%lld\n",max(sum1+minbc,sum3+minab));
    }
    return 0;
}

 


G - Bounce(找規律)

For Argo, it is very interesting watching a circle bouncing in a rectangle.

As shown in the figure below, the rectangle is divided into N×M grids, and the circle fits exactly one grid.

The bouncing rule is simple:

1. The circle always starts from the left upper corner and moves towards lower right.

2. If the circle touches any edge of the rectangle, it will bounce.

3. If the circle reaches any corner of the rectangle after starting, it will stop there.

Argo wants to know how many grids the circle will go through only once until it first reaches another corner. Can you help him?

Input

The input consists of multiple test cases. (Up to 105)

For each test case:

One line contains two integers N and M, indicating the number of rows and columns of the rectangle. (2 ≤ N, M ≤ 109)

Output

For each test case, output one line containing one integer, the number of grids that the circle will go through exactly once until it stops (the starting grid and the ending grid also count).

Sample Input

2 2
2 3
3 4
3 5
4 5
4 6
4 7
5 6
5 7
9 15

Sample Output

2
3
5
5
7
8
7
9
11
39

【分析】找規律(思路規律__here!

這道題光找規律找了三個小時,找出來規律之後才發現題目原來很簡單。

先算出來小球一共會經過多少網格(包括重複的在內)

再算出來有多少個網格過不止一次,兩者相減就可以了。

對於n*m的矩形,經過觀察可以得到,小球彈跳中經過的網格總數是(n−1)×(m−1)gcd((n−1),(m−1))+1

.

可以算得 球在9*15的方格中會經過57個網格

然後又經過觀察可以看出來,其實9*15的矩形(圖中示意)和5*8的矩形是相似的,即5*8擴大一倍可以得到9*15的矩形。

左邊是9*15的網格 右邊是5*8的網格。

這兩個網格中的相交點都是一樣的,都是9個,而(5-2)*(8-2)正好等於9*2!

而57-9*2就是答案39.

又是經過觀察,顯然可以得到一個結論:交點數等於 (n-2)*(m-2)/gcd(n,m)

而只經過一次的點就是57-9*2=39.

這樣我們就得到了總的公式

【程式碼】

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

ll gcd(ll a,ll b)
{
	return b==0?a:gcd(b,a%b);
}

int main()
{
	ll n,m;
    while(~scanf("%lld%lld",&n,&m))
    {
    	if(n==m)
    	{
    		printf("%lld\n",n);
    		continue;
		}
		else if(n>m) swap(n,m);
		ll g1=gcd(n-1,m-1);
		ll g2=((n-1)/g1)*(m-1);
		ll x=(n-1)/g1;
		ll y=(m-1)/g1;
		ll ans=g2-(x-1)*(y-1)+1;
		printf("%lld\n",ans);
	}
	return 0;
}

I - Minimum(線段樹模板題)

You are given a list of integers a0, a1, …, a2^k-1.

You need to support two types of queries:

1. Output Minx,y∈[l,r] {ax∙ay}.

2. Let ax=y.

Input

The first line is an integer T, indicating the number of test cases. (1≤T≤10).

For each test case:

The first line contains an integer k (0 ≤ k ≤ 17).

The following line contains 2k integers, a0, a1, …, a2^k-1 (-2k ≤ ai < 2k).

The next line contains a integer  (1 ≤ Q < 2k), indicating the number of queries. Then next Q lines, each line is one of:

1. 1 l r: Output Minx,y∈[l,r]{ax∙ay}. (0 ≤ l ≤ r < 2k)

2. 2 x y: Let ax=y. (0 ≤ x < 2k, -2k ≤ y < 2k)

Output

For each query 1, output a line contains an integer, indicating the answer.

Sample Input

1
3
1 1 2 2 1 1 2 2
5
1 0 7
1 1 2
2 1 2
2 2 2
1 1 2

Sample Output

1
1
4

【分析】線段樹模板題

【程式碼】https://blog.csdn.net/haut_ykc/article/details/78073915

#include<set>  
#include<map>     
#include<stack>            
#include<queue>            
#include<vector>    
#include<string> 
#include<time.h>
#include<math.h>            
#include<stdio.h>            
#include<iostream>            
#include<string.h>            
#include<stdlib.h>    
#include<algorithm>   
#include<functional>    
using namespace std;            
#define ll long long       
#define inf  1000000000000000000       
#define mod 1000000007             
#define maxn  1360100
#define lowbit(x) (x&-x)            
#define eps 1e-9
ll a[maxn*4];
ll maxs[maxn*4],mins[maxn*4];
void build(ll id,ll l,ll r)
{
	ll m;
	if(l==r)
	{
		scanf("%lld",&maxs[id]);
		mins[id]=maxs[id];
		return ;
	}
	    m=(l+r)/2;
		build(id<<1,l,m);
	    build((id<<1)+1,m+1,r);
	    maxs[id]=max(maxs[id*2],maxs[id*2+1]);
		mins[id]=min(mins[id*2],mins[id*2+1]);
}
ll query(ll id,ll l,ll r,ll L, ll R)
{
	ll ret=-inf;
	if(l<=L && r>=R)
		return maxs[id];
	ll m=(L+R)/2;
	if(l<=m)
		ret=max(ret,query(id<<1,l,r,L,m));
	if(r>m)
		ret=max(ret,query((id<<1)+1,l,r,m+1,R));
	return ret;
}
ll query1(ll id,ll l,ll r,ll L, ll R)
{
	ll ret=inf;
	if(l<=L && r>=R)
		return mins[id];
	ll m=(L+R)/2;
	if(l<=m)
		ret=min(ret,query1(id<<1,l,r,L,m));
	if(r>m)
		ret=min(ret,query1((id<<1)+1,l,r,m+1,R));
	return ret;
}
void updata(ll x,ll y,ll l,ll r,ll id)
{
	if(l==r)
	{
		maxs[id]=y;
		mins[id]=y;
		return ;
	}
	ll m=(l+r)/2;
	if(x<=m)
		updata(x,y,l,m,id*2);
	else
		updata(x,y,m+1,r,id*2+1);
	maxs[id]=max(maxs[id*2],maxs[id*2+1]);
	mins[id]=min(mins[id*2],mins[id*2+1]);
}
int  main(void)
{
	ll  n,m,i,j,T;
	ll  str;
	scanf("%lld",&T);
	while(T--)
	{
		ll b,c;
		scanf("%lld",&n);
		n=(1<<n);
		build(1,1,n);
		scanf("%lld",&m);
		for(i=1;i<=m;i++)
		{
			scanf("%lld",&str);
			scanf("%lld%lld",&b,&c);
			b++;c++;
			if(str==1)
			{
				ll ans=query1(1,b,c,1,n)*query1(1,b,c,1,n);
				ans=min(ans,query(1,b,c,1,n)*query1(1,b,c,1,n));
				ans=min(ans,query(1,b,c,1,n)*query(1,b,c,1,n));
				printf("%lld\n",ans);
			}
			else
			     c--,updata(b,c,1,n,1);
		}
	}
	return 0;
}