周末训练笔记+ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛+2017 ACM-ICPC 亚洲区(南宁赛区)网络赛(9.23,9.24)

来源:互联网 发布:java常见注解 编辑:程序博客网 时间:2024/05/16 01:21

北京和南宁这两场下来算是对线段树的了解更加深刻了,北京那一场的典型的单点更新,但是因为差两个,写了个很多的代码,超时了,赛后看题解,建了两棵树,我这心里是****的,差点给我气成傻×,自己的树真是用的太不灵活了,南宁的有个题,有人用线段树ac了,但是我感觉不用也一样,用了反而费劲,(代码还没调出来),其他题目的槽点具体到题目里。

ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛

ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 

Visiting Peking University

这个题是队友写的,大体意思就是给你一个n和m,你要拿出连续m天,其中两天去北京大学,第一天必须去北京大学,另一天随意,然后第二行给出n天中北京大学排队的人数,第三行给出交通限行的日子,就是这几天哪里都不能去,拟定一个k,需要满足k-m刚好等于这k天里的交通限行的天数,现在求去北京大学参观排队最少的是那两天

乍一看挺复杂的,明白了题意,模拟即可,详见代码

Bounce

给出一个矩形的阵,小球从左上角出发,沿着正方形的对角线走,不能原路返回,走到任意一个角落停止,重复的不计,问你一共走过了多少方格

这个这个  推公式   gg

Minimum

给出一个n,代表2^n个数据,然后m次询问,每次temp,l,r,当temp==1,求[l,r]上map[x]*map[y]的最小值

map[x],map[y]可以相等lr可以相等,temp==2,map[x]=y。

哇,看到这个题,以为线段树专题可以大显神威了,差点被题给坑死,首先看错题,output{ax*ay}误以为output{ax……ay}样例始终搞不明白,第二次错题意,下限,这次是读题不认真,没注意可以去负值,写完的代码废了一般。我的解法是和题解思路一样的,只是找的过程不一样,首先第一种情况,如果区间内都是负值,则肯定要找找最大的那一个,第二种,全是正值,找最小的那一个,第三种,政府都有,找到最大的正最小的负,结束,只建立了一棵树,我在找出第一个数的时候,第二个数与这个数乘积在区间内暴力测试,全部过一遍,然后超时,最后看题解气成傻*,简两棵树,一个大的,一个小的,完美,(摊手)。。。

2017 ACM-ICPC 亚洲区(南宁赛区)网络赛

 Train Seats Reservation

给出n张订单,下面b行给出s,e,k分别代表上车,下车,所需要的座位数量,任意两个人没有冲突的情况下求最少需要多少座位

这个题挺水的,只要能注意到下车的地方是不计入的,只要查查这个车站重叠了几次,然后把这几次的k都加上,然后遍历一遍,找出最大值即可

Overlapping Rectangles

给出n个长方形的对角线的左边,求出去重叠部分的总面积,也就是最后形成的不规则图形的面积

我的思路是先写出计算两个长方形重叠的面积,然后只要添加一个新的长方形就往前找,然后加上当前的这个的面积,减去与前面重叠的面积,他们有人用线段树A的,结束后向其他队借了个代码,可以,很强势

The Heaviest Non-decreasing Subsequence Problem

给你一行数,小于0的,重量0,大于10000的,权值为x-10000,重量为5,其他为1

ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛

描述

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.

输入

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.

输出

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

样例输入
7 36 9 10 1 0 8 353 5 6 24 210 11 1 21 2
样例输出
0 31 3
#include <iostream>#include <stdio.h>#include <cstring>#include <algorithm>#include <string>using namespace std;int main(){    int n;    int m1;    while (scanf("%d%d",&n,&m1)!=EOF)    {       int a[n];       int flag[n];       for (int i = 0; i < n; i++)       {           scanf("%d",&a[i]);           flag[i] = 0;       }       int m;       scanf("%d",&m);       for (int i = 0; i < m; i++)       {           int q;           scanf("%d",&q);           flag[q] = 1;       }       int min = 99999999;       int min_i = 0;       int min_j = 0;       for (int i = 0; i < n; i++)       {           int y = i + m1 - 1;           if (flag[i] == 1)           continue;           int flag1 = 0;           for (int j = i + 1; j <= y; j++)           {                if (flag[j] == 1){                    y++;                    continue;                }                if (y >= n){                    flag1 = 1;                break;                }           }           if (flag1 == 1)           continue;           for (int j = i + 1; j <= y; j++){               if (min > a[i] + a[j] && flag[j] != 1){                    min = a[i] + a[j];                    min_i = i;                    min_j = j;                }           }       }       printf("%d %d\n",min_i,min_j);    }    return 0;}

描述

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?

输入

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)

输出

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).

样例输入
2 22 33 43 54 54 64 75 65 79 15
样例输出
235578791139
#include<iostream>using namespace std;long long gcd(long long a,long  long b){    if(b==0)    return a;    return gcd(b,a%b);    }int main(){    long long  n,m;    //cout<<gcd(6,21);    while(cin>>n>>m)    {        if(n<m)        swap(n,m);        long long  temp=gcd(n-1,m-1);        long long  k=(m-1)/temp;        long long  x=(n-1)/temp;        long long  ans=(k-1)*(m-k+1)+(x-k+1)*(m-k);        cout<<ans+1<<endl;        }    return 0;    }

描述

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.

输入

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, -2≤ y < 2k)

输出

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

样例输入
131 1 2 2 1 1 2 251 0 71 1 22 1 22 2 21 1 2
样例输出
114
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int maxn=200005;int mapmax[maxn<<2];int mapmin[maxn<<2];int map[maxn];void Pushup(int rt){    mapmax[rt]=max(mapmax[rt<<1],mapmax[rt<<1|1]);    mapmin[rt]=min(mapmin[rt<<1],mapmin[rt<<1|1]);    }void build(int l,int r,int rt){    if(l==r){        mapmax[rt]=map[l];        mapmin[rt]=map[l];        return;    }    int m=(l+r)>>1;    build(l,m,rt<<1);    build(m+1,r,rt<<1|1);    Pushup(rt);}void update(int L,int C,int l,int r,int rt){    if(l==r){        mapmin[rt]=C;        mapmax[rt]=C;        return;    }    int m=(l+r)>>1;    if(L<=m)        update(L,C,l,m,rt<<1);    else        update(L,C,m+1,r,rt<<1|1);    Pushup(rt);}int querymax(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R)        return mapmax[rt];    int m=(l+r)>>1;    int ans=-1000000000;    if(L<=m)        ans=max(ans,querymax(L,R,l,m,rt<<1));    if(R>m)        ans=max(ans,querymax(L,R,m+1,r,rt<<1|1));    return ans;    }int querymin(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R)        return mapmin[rt];    int m=(l+r)>>1;    int ans=1000000000;    if(L<=m)        ans=min(ans,querymin(L,R,l,m,rt<<1));    if(R>m)        ans=min(ans,querymin(L,R,m+1,r,rt<<1|1));    return ans;    }int main(){    int t;    int n,m;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        n=(int)pow(2.0,n);        for(int i=1;i<=n;i++)        {            scanf("%d",&map[i]);            }        build(1,n,1);        scanf("%d",&m);        int a,b,c;        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&c,&a,&b);            a++;            if(c==1)            {                b++;                long long  mmax=querymax(a,b,1,n,1);                long long  mmin=querymin(a,b,1,n,1);                if(mmax<=0)printf("%lld\n",mmax*mmax);                else if(mmin>=0) printf("%lld\n",mmin*mmin);                else printf("%lld\n",mmin*mmax);                }            else            {                update(a,b,1,n,1);                }            }        }    return 0;    }

2017 ACM-ICPC 亚洲区(南宁赛区)网络赛

You are given a list of train stations, say from the station 11 to the station 100100.

The passengers can order several tickets from one station to another before the train leaves the station one. We will issue one train from the station 11 to the station 100100 after all reservations have been made. Write a program to determine the minimum number of seats required for all passengers so that all reservations are satisfied without any conflict.

Note that one single seat can be used by several passengers as long as there are no conflicts between them. For example, a passenger from station 11 to station 1010 can share a seat with another passenger from station 3030to 6060.

Input Format

Several sets of ticket reservations. The inputs are a list of integers. Within each set, the first integer (in a single line) represents the number of orders, nn, which can be as large as 10001000. After nn, there will be nn lines representing the nn reservations; each line contains three integers s, t, ks,t,k, which means that the reservation needs kk seats from the station ss to the station tt .These ticket reservations occur repetitively in the input as the pattern described above. An integer n = 0n=0 (zero) signifies the end of input.

Output Format

For each set of ticket reservations appeared in the input, calculate the minimum number of seats required so that all reservations are satisfied without conflicts. Output a single star '*' to signify the end of outputs.

样例输入

21 10 820 50 2032 30 520 80 2040 90 400

样例输出

2060*
#include<iostream>#include<stdio.h>#include<string.h>#include<string>#include<algorithm>using namespace std;long long map[10000010];int main(){    int n;    while(cin>>n)    {        if(n==0)        {            cout<<"*"<<endl;            break;            }        memset(map,0,sizeof(map));        long long l,r,k;        long long maxr=0;        for(int i=0;i<n;i++)        {            scanf("%lld %lld %lld",&l,&r,&k);            if(r>maxr)            maxr=r;            for(int i=l;i<r;i++)            {                map[i]+=k;                }            }        long long max=-100;        for(int i=1;i<maxr;i++)        if(map[i]>max)        max=map[i];        cout<<max<<endl;        }    return 0;    }

There are nn rectangles on the plane. The problem is to find the area of the union of these rectangles. Note that these rectangles might overlap with each other, and the overlapped areas of these rectangles shall not be counted more than once. For example, given a rectangle AA with the bottom left corner located at (0, 0)(0,0) and the top right corner at (2, 2)(2,2), and the other rectangle BB with the bottom left corner located at (1,1)(1,1) and the top right corner at (3,3)(3,3), it follows that the area of the union of AA and BB should be 77, instead of 88.

Although the problem looks simple at the first glance, it might take a while to figure out how to do it correctly. Note that the shape of the union can be very complicated, and the intersected areas can be overlapped by more than two rectangles.

Note:

(1) The coordinates of these rectangles are given in integers. So you do not have to worry about the floating point round-off errors. However, these integers can be as large as 1,000,0001,000,000.

(2) To make the problem easier, you do not have to worry about the sum of the areas exceeding the long integer precision. That is, you can assume that the total area does not result in integer overflow.

Input Format

Several sets of rectangles configurations. The inputs are a list of integers. Within each set, the first integer (in a single line) represents the number of rectangles, n, which can be as large as 10001000. After n, there will be n lines representing the n rectangles; each line contains four integers <a, b, c, d><a,b,c,d> , which means that the bottom left corner of the rectangle is located at (a, b)(a,b), and the top right corner of the rectangle is located at (c, d)(c,d). Note that integers aabbccdd can be as large as 1,000,0001,000,000.

These configurations of rectangles occur repetitively in the input as the pattern described above. An integer n = 0n=0 (zero) signifies the end of input.

Output Format

For each set of the rectangles configurations appeared in the input, calculate the total area of the union of the rectangles. Again, these rectangles might overlap each other, and the intersecting areas of these rectangles can only be counted once. Output a single star '*' to signify the end of outputs.

样例输入

20 0 2 21 1 3 330 0 1 12 2 3 34 4 5 50

样例输出

73*
#include <cstdio>#include <cstring>#include <cctype>#include <algorithm>using namespace std;#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1#define LL long longconst int maxn = 2222;LL cnt[maxn << 2];LL sum[maxn << 2];LL X[maxn];struct Seg {    LL h,l,r;    int s;    Seg(){}    Seg(LL a,LL b,LL c,LL d) : l(a) , r(b) , h(c) , s(d) {}    bool operator < (const Seg &cmp) const {        return h < cmp.h;    }}ss[maxn];void PushUp(int rt,int l,int r) {    if (cnt[rt]) sum[rt] = X[r+1] - X[l];    else if (l == r) sum[rt] = 0;    else sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void update(int L,int R,int c,int l,int r,int rt) {    if (L <= l && r <= R) {        cnt[rt] += c;        PushUp(rt , l , r);        return ;    }    int m = (l + r) >> 1;    if (L <= m) update(L , R , c , lson);    if (m < R) update(L , R , c , rson);    PushUp(rt , l , r);}int Bin(LL key,LL n,LL X[]) {    int l = 0 , r = n - 1;    while (l <= r) {        int m = (l + r) >> 1;        if (X[m] == key) return m;        if (X[m] < key) l = m + 1;        else r = m - 1;    }    return -1;}int main() {    int n , cas = 1;    while (~scanf("%d",&n) && n) {        int m = 0;        while (n --) {            int a , b , c , d;            scanf("%d%d%d%d",&a,&b,&c,&d);            X[m] = a;            ss[m++] = Seg(a , c , b , 1);            X[m] = c;            ss[m++] = Seg(a , c , d , -1);        }        sort(X , X + m);        sort(ss , ss + m);        int k = 1;        for (int i = 1 ; i < m ; i ++) {            if (X[i] != X[i-1]) X[k++] = X[i];        }        memset(cnt , 0 , sizeof(cnt));        memset(sum , 0 , sizeof(sum));        int ret = 0;        for (int i = 0 ; i < m - 1 ; i ++) {            int l = Bin(ss[i].l , k , X);            int r = Bin(ss[i].r , k , X) - 1;            if (l <= r) update(l , r , ss[i].s , 0 , k - 1, 1);            ret += sum[1] * (ss[i+1].h - ss[i].h);        }        printf("%d\n",ret);    }     printf("*");    return 0;}

Let SS be a sequence of integers s_{1}s1s_{2}s2......s_{n}sn Each integer is is associated with a weight by the following rules:

(1) If is is negative, then its weight is 00.

(2) If is is greater than or equal to 1000010000, then its weight is 55. Furthermore, the real integer value of s_{i}si is s_{i}-10000si10000 . For example, if s_{i}si is 1010110101, then is is reset to 101101 and its weight is 55.

(3) Otherwise, its weight is 11.

A non-decreasing subsequence of SS is a subsequence s_{i1}si1s_{i2}si2......s_{ik}sik, with i_{1}<i_{2}\ ...\ <i_{k}i1<i2 ... <ik, such that, for all 1 \leq j<k1j<k, we have s_{ij}<s_{ij+1}sij<sij+1.

A heaviest non-decreasing subsequence of SS is a non-decreasing subsequence with the maximum sum of weights.

Write a program that reads a sequence of integers, and outputs the weight of its

heaviest non-decreasing subsequence. For example, given the following sequence:

8080 7575 7373 9393 7373 7373 1010110101 9797 -11 -11 114114 -11 1011310113 118118

The heaviest non-decreasing subsequence of the sequence is <73, 73, 73, 101, 113, 118><73,73,73,101,113,118> with the total weight being 1+1+1+5+5+1 = 141+1+1+5+5+1=14. Therefore, your program should output 1414 in this example.

We guarantee that the length of the sequence does not exceed 2*10^{5}2105

Input Format

A list of integers separated by blanks:s_{1}s1s_{2}s2,......,s_{n}sn

Output Format

A positive integer that is the weight of the heaviest non-decreasing subsequence.

样例输入

80 75 73 93 73 73 10101 97 -1 -1 114 -1 10113 118

样例输出

14
#include<iostream>#include<stdio.h>#include<string.h>#include<cstdio>#include<algorithm>using namespace std;long long  map[1000010];//int len[1000010];int d[1000010];int main(){    int n;    long long temp;    int num=1;    while(~scanf("%lld",&temp))    {        //for(int i=1;i<=n;i++)        //{            //scanf("%lld",&temp);            if(temp<0)            {               continue;            }            else if(temp>=10000)            {                for(int j=0;j<5;j++)                {                    map[num]=temp-10000;                    num++;                }                }            else {                map[num]=temp;                num++;            }        }        //cout<<num<<endl;       // }            //}       // for(int i=0;i<num;i++)        //cout<<map[i]<<" ";        /*int max=0;        for(int i=0;i<num;i++)        {            len[i]=1;            for(int j=0;j<i;j++)            {                if(map[j]<=map[i]&&len[j]+1>len[i])                    len[i]=len[j]+1;                }            if(max<len[i])                max=len[i];            }*/        d[1]=map[1];  //初始化        int len=1;        for (int i=2;i<=num;i++)        {            if (map[i]>=d[len]) d[++len]=map[i];            else            {                int j=upper_bound(d+1,d+len+1,map[i])-d;                d[j]=map[i];            }            }        cout<<len<<endl;    return 0;    }

阅读全文
1 0
原创粉丝点击