20190402訓練賽

Problem A  Patches
1 s, 256 MB

【Description】Carlos is very concerned with the environment. Whenever possible, he tries to use less polluting

means of transport. He recently got a job close to home and is now using his bike to go to work.

Unfortunately, in the route between his home and his job there is a nail factory, and often some

nails fall from their trucks, and end up puncturing Carlos’ bike tires. Therefore he ends up having to

make several patches on the tires of his bike.

To make the repairs, Carlos uses two different types of patches. Both types are as wide as a bike

tire, but differ in length. As the cost of the patch is proportional to its length, Carlos is trying to find

a way to save money, using the least possible length of patches to make the repairs, without cutting

the patches.

The first step in repairing a tire is making a chalk mark on a position of the tire and then writing

down the distances, measured clockwise, of each of the holes in relation to the chalk mark. Each hole

must be completely covered by a patch. Carl~ao would like your help to determine, given the positions

of the holes, the most economic way to make the repair.

【Input】

The input contains two lines. The first line contains four integers N; C; T1 e T2. Integer N indicates

the number of holes in the tire, and C indicates the cirunference length of the tire, in centimeters.

The lengths of the patches in centimeters are given by integers T1 and T2. The second line contains

N integers Fi, representing the distance, in clockwise direction, from the chalk mark to hole i, in

centimeters.

【Output】

Your program must print a single line, containing a single integer, the smallest total length of patches

needed to make all the repairs.

題意:

一個輪胎上破了n個洞,現有兩個長度不一樣的補丁,要求使用最短長度的補丁補上這n個洞,一個補丁可以一下補很多個洞

 

一開始想貪心,然後就沒貪出來...意識到可能要用區間dp,然後就不想寫了,,比賽完了補題時才發現也就是個板子題目......

三重循環枚舉長度,起點,分割點,然後先判斷一下起點到枚舉的終點能不能用一個補丁補完,這裏得先用小的判斷。

然後就剩下的就正常做就好了。

#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI  acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x)  priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
int a[1010],n,c,t1,t2,dp[1010][1010];
int main()
{
    while(~scanf("%d%d%d%d",&n,&c,&t1,&t2)){
            if(t1>t2)
            swap(t1,t2);
            memset(a,0,sizeof(a));
            memset(dp,inf,sizeof(dp));
      for(int i=1;i<=n;i++){
        sc(a[i]);
        dp[i][i]=t1;
      }
      for(int i=2;i<=n;i++)
       for(int j=1;j+i-1<=n;j++){
        int ends=j+i-1;
         if(a[ends]-a[j]<=t1)      //判斷兩個補丁能否補下
            dp[j][ends]=t1;
         else if(a[ends]-a[j]<=t2)
            dp[j][ends]=t2;
        for(int k=j;k<ends;k++){
            dp[j][ends]=min(dp[j][ends],dp[j][k]+dp[k+1][ends]);
        }
       }
       printf("%d\n",dp[1][n]);
    }
}
/*
5 20 2 3
2 5 8 11 15
*/
/*
4 20 12 9
1 2 3 13
*/

【Problem E-Dangerous Dive】

【Description】 The recent earthquake in Nlogonia did not affect too much the buildings in the capital, which was at the epicenter of the quake. But the scientists found that it affected the dike wall, which now has a significant structural failure in its underground part that, if not repaired quickly, can cause the

collapse of the dike, with the consequent flooding the whole capital.

The repair must be done by divers, at a large depth, under extremely difficult and dangerous

conditions. But since the survival of the city is at stake, its residents came out in large numbers to

volunteer for this dangerous mission.

As is traditional in dangerous missions, each diver received at the start of his/her mission a small

card with an identification number. At the end of their mission, the volunteers returned the nameplate,

placing it in a repository.

The dike is safe again, but unfortunately it seems that some volunteers did not return from their

missions. You were hired for the grueling task of, given the plates placed in the repository, determine

which volunteers lost their lives to save the city.

Input

The input is composed of two lines. The first line contains two integers N and R, indicating respectively

the number of volunteers that went to the mission and the number of volunteers that returned from

the mission. Volunteers are identified by numbers from 1 to N. The second line contains R integers,

indicating the volunteers which returned from the mission (at least one volunteer returned).

Output

Your program must produce a single line containing the identifiers of the volunteers who did not

return from their missions, in ascending order of their identifications. Leave a blank space after each

identifier (notice that, therefore, there must be a blank space after the last identifier in the line). If

every volunteer returned, the line must contain a single character ‘*’ (asterisc).

這是個水題了,n個人編號1-n,然後輸入<=n個數,判斷哪些數沒有然後輸出,全都有就輸出“*”

#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI  acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x)  priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=1e4+10;
int vis[N],n,m;
int main()
{
    while(~sc(n)){
        sc(m);
        int x;
        memset(vis,1,sizeof(vis));
        for(int i=1;i<=m;i++){
            sc(x);
            vis[x]=0;
        }
        bool flag=false;
        for(int i=1;i<=n;i++){
            if(vis[i]){
                    flag=true;
                printf("%d ",i);
            }
        }
        if(!flag)
            printf("*");
        printf("\n");
    }
}

【Problem F-Triangles】

【Description】You will be given N points on a circle. You must write a program to determine how many distinct equilateral triangles can be constructed using the given points as vertices.

【Input】

The first line of the input contains an integer N, the number of points given. The second line contains N integers Xi, representing the lengths of the circular arcs between two consecutive points in the circle: for 1 ≤ i ≤ (N − 1), Xi represents the length of the arc between between points i and i + 1; XN represents the length of the arc between points N and 1.

【Output】

Your program must output a single line, containing a single integer, the number of distinct equilateral triangles that can be constructed using the given points as vertices.

在一個圓上標有n個點構成的n個弧的長度,問這n個點能組成多少個正三角形。

很明顯這個題需要用到前綴和,題目要求正三角形,所以也就是選出來的三個點之間的弧的長度要相等,所以這裏在開一個數組記錄前綴和,然後用map儲存,在枚舉每一個點看看這個點加上圓弧長的1/3,和2/3是否有點,有就ans就加1.

如果圓的周長不能被3整除,那麼就肯定一個正三角形都沒有。

#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI  acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x)  priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=1e5+10;
map<int,int>mp;
int n,a[N];
int main()
{
    while(~sc(n)){
            int x;
    mp.clear();
    memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++){
            sc(x);
            a[i]=a[i-1]+x;
            mp[a[i]]=1;
        }
        if(a[n]%3!=0)
            printf("0\n");
        else{
               int ans=0;
            for(int i=1;i<=n;i++)
                if(mp[a[i]+a[n]/3]&&mp[a[i]+2*(a[n]/3)]){
                    ans++;
            }
            printf("%d\n",ans);
        }
    }
}

Guessing Camels

Description

Jaap, Jan, and Thijs are on a trip to the desert after having attended the ACM ICPC World Finals 2015 in Morocco. The trip included a camel ride, and after returning from the ride, their guide invited them to a big camel race in the evening. The camels they rode will also participate and it is customary to bet on the results of the race. 
One of the most interesting bets involves guessing the complete order in which the camels will finish the race. This bet offers the biggest return on your money, since it is also the one that is the hardest to get right. 
Jaap, Jan, and Thijs have already placed their bets, but the race will not start until an hour from now, so they are getting bored. They started wondering how many pairs of camels they have put in the same order. If camel cc is before camel d on Jaap’s, Jan’s and Thijs’ bet, it means that all three of them put c and d in the same order. Can you help them to calculate the number of pairs of camels for which this happened? 
題意:

有三組數據,每組n個1-n的數,在三組數中都滿足一個數在另一個數前面,答案就+1,問最後答案是多少

舉個例子:

4

2 3 1 4

2 1 4 3

2 4 3 1

三組數中,2都在1前面,2都在4前面,2都在3前面,所以最後輸出3

這個題正解或許是CDQ分治?最近雖然在學CDQ分治,可惜還沒學會,還是用樹狀數組做的。

這個題直接求可能比較麻煩,可以先求出來不滿足的,然後用總數一減就是答案,那麼不滿足的怎麼求?

可以先記錄第一個數組中的數的編號,即p[a[x]]=i,然後去從後往前看第二個數組,因爲不包含位置是等於的情況(即2肯定不在2前面)所以先從後往前求第二個數組中的數在第一個數組中的位置,調用求和的函數,求第一個數組中有多少個數在這個數前面,ans就加多少,因爲第二個數組是從後往前掃,這樣求出來的就是不滿足條件的,然後再把這個數的位置也更新進去。

然後可以用類似的辦法求第二個數組和第三個數組,第三個數組和第一個數組,類似於兩兩求逆序對的情況,最後做差即可。

注意記錄的變量要用longlong

#include<bits/stdc++.h>
#define lowbit(x) (x)&(-x)
using namespace std;
const int N=2e5+10;
int n,p[N],a[N],b[N],c[N],sum[N];
long long ans;
int solve(int x)
{
    int ans=0;
    while(x){
        ans+=sum[x];
        x-=lowbit(x);
    }
    return ans;
}
void update(int x)
{
    while(x<=n){
        sum[x]++;
        x+=lowbit(x);
    }
}
int main()
{
    while(~scanf("%d",&n)){
            memset(sum,0,sizeof(sum));
            memset(p,0,sizeof(p));
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            p[a[i]]=i;
        }
        for(int i=1;i<=n;i++)
            scanf("%d",&b[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&c[i]);
            ans=0;
        for(int i=n;i>=1;i--){
            ans+=solve(p[b[i]]);
            update(p[b[i]]);
        }
        for(int i=1;i<=n;i++){
            p[b[i]]=i;
            sum[i]=0;
        }
        for(int i=n;i>=1;i--){
            ans+=solve(p[c[i]]);
            update(p[c[i]]);
        }
        for(int i=1;i<=n;i++){
            p[c[i]]=i;
            sum[i]=0;
        }
        for(int i=n;i>=1;i--){
            ans+=solve(p[a[i]]);
            update(p[a[i]]);
        }
        printf("%lld\n",(1LL*n*(n-1)-ans)>>1);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章