Codeforces Round #329 (Div. 2) (593A,593B,593C,593D)

来源:互联网 发布:方可进销存软件下载 编辑:程序博客网 时间:2024/06/15 01:01

2Char

题目链接:

http://codeforces.com/problemset/problem/593/A

解题思路:

For each letter will maintain the total length of words (cnt1ci), which found it was alone, and for each pair of letters will maintain the total length of words that contains only them (cnt2ci, cj).

For each row, count a number of different letters in it. If it is one, then add this letter to the length of the word. If two of them, then add to the pair of letters word`s length.

Now find a pair of letters that will be the answer. For a pair of letters ci, cj answer is cnt1ci + cnt1cj + cnt2ci, cj. Among all these pairs find the maximum. This is the answer.

The overall complexity is O (total length of all strings + 26 * 26)

算法思想:

没什么难的,想清楚了一下子就写出来了,2个字母,最多26*26,所以用一个二位数组保存就行了,注意只有一个字母的情况。

AC代码:

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>using namespace std;char str[105][1005];int num1[35][35];int num2[35];int ch[5];int main(){    int n;    while(~scanf("%d",&n)){        memset(num1,0,sizeof(num1));        for(int i = 0; i < n; i++){            scanf("%s",str[i]);            int l = strlen(str[i]),sum = 0,flag = 0;            memset(num2,0,sizeof(num2));            memset(ch,0,sizeof(ch));            for(int j = 0; j < l; j++){                num2[str[i][j]-'a']++;                sum++;            }            int dis = 0;//字母的个数            for(int j = 0; j < 30; j++){                if(num2[j]){                    ch[dis++] = j;                }                if(dis >= 3){                    flag = 1;                    break;                }            }            if(flag)                continue;            if(ch[1] == 0){                for(int j = 0; j < ch[0]; j++)                    num1[j][ch[0]] += sum;                for(int j = ch[0]+1; j < 30; j++)                    num1[ch[0]][j] += sum;            }            else{                if(ch[0] > ch[1])                    swap(ch[0],ch[1]);                num1[ch[0]][ch[1]] += sum;            }        }        int ans = 0;        for(int i = 0; i < 30; i++){            for(int j = 0; j < 30; j++){                ans = max(ans,num1[i][j]);            }        }        printf("%d\n",ans);    }    return 0;}

Anton and Lines

题目链接:

http://codeforces.com/problemset/problem/593/B

解题思路:

Note that if a s line intersects with the j th in this band, and at x = x1 i th line is higher, at x = x2 above would be j th line. Sort by ycoordinate at x = x1 + eps, and x = x2 - eps. Verify that the order of lines in both cases is the same. If there is a line that its index in the former case does not coincide with the second, output Yes. In another case, derive No. The only thing that can stop us is the intersection at the borders, as in this case we dont know the sorts order. Then add to our border x1 small eps, and by x2 subtract eps, and the sort order is set uniquely. The overall complexity is O(nlogn)

这题想多了,其实只要用两个相同的结构体保存,一个根据y1排序,一个根据y2排序,然后再O(n)的查找就行了。

AC代码:

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>using namespace std;typedef long long ll;ll k[100005],b[100005];int vis[100005];struct node{    int id;    ll y1,y2;}no1[100005],no2[100005];bool cmp1(node a,node b){    if(a.y1 == b.y1)        return a.y2 < b.y2;    return a.y1 < b.y1;}bool cmp2(node a,node b){    if(a.y2 == b.y2)        return a.y1 < b.y1;    return a.y2 < b.y2;}int main(){    int n;    while(~scanf("%d",&n)){        memset(vis,0,sizeof(vis));        ll x1,x2;        scanf("%lld%lld",&x1,&x2);        for(int i = 0; i < n; i++){            scanf("%lld%lld",&k[i],&b[i]);            no1[i].id = i;no2[i].id = i;            no1[i].y1 = no2[i].y1 = k[i]*x1+b[i];            no1[i].y2 = no2[i].y2 = k[i]*x2+b[i];        }        sort(no1,no1+n,cmp1);        sort(no2,no2+n,cmp2);        int k = 0,flag = 0;        for(int i = 0; i < n; i++){            while(no1[i].y1 == no2[k].y1 || vis[k])                k++;            if(k < n && no1[i].y2 > no2[k].y2){                flag = 1;                break;            }            vis[i] = 1;        }        if(flag)            printf("YES\n");        else            printf("NO\n");    }    return 0;}


Beautiful Function

题目链接:

http://codeforces.com/problemset/problem/593/C

解题思路:

One of the answers will be the amount of such expressions for each circle in the coordinate x and similarly coordinate y

For a = 1b = abs(t - i), it can be written as 

Consider the a - b + abs(a - b):

if a ≤ b, то a - b + abs(a - b) = 0,

if a > b, то a - b + abs(a - b) = 2a - 2b

Now consider what means a > b:

1 > abs(t - i)

i > t - 1 and i < t + 1.

For integer i is possible only if i = t.

That is, this bracket is not nullified only if i = t.

Consider the 2a - 2b = 2 - 2 * abs(t - i) = 2. Then  differs from the wanted position by no more than 1, but since all the radiuses are not less than 2, then this point belongs to the circle.

The overall complexity is O(n).

算法思想:

根据quailty大牛贴吧回答来的:

先特判掉1个点的情形,
然后尝试将x坐标和y坐标分开考虑,
对于x坐标,希望能够找到一个f(t)使得f(i)=x[i],i=1,2,...,n,
由于可以使用绝对值函数,
考虑构造一个f(t)=\sum_{i=1}^{n}{a[i]*abs(t-i)},
但是发现每一段的斜率奇偶性是相同的,
亦即所有x[i]-x[i-1](i=2,3,...,n)的奇偶性是相同的,
很显然这不能保证,
注意到每个圆的半径至少是2,
即使把每个点的横纵坐标都改变1,还是在各自的圆内,
因此可以将所有奇数坐标-1,
那么容易知道a[i]=((x[i+1]-x[i])-(x[i]-x[i-1]))/2,i=2,3,...,n-1,
再利用第一段的斜率x[2]-x[1]可以得到a[1]-a[n]的值,
不妨令a[n]=0,于是a[1]也可以知道,
那么此时已经满足f(i)-f(i-1)=x[i]-x[i-1],i=2,3,...,n,
再补上一个常数使得f(1)=x[1]即可,
输出异常恶心,特别要注意如果中间系数<0或者>50,也要拆开来写。

AC代码:

#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>using namespace std;int x[55],y[55],d[55],a[55];vector<pair<int,int> >v;void work(int n){    for(int i=1;i<n;i++)        d[i]=x[i]-x[i-1];    for(int i=2;i<n;i++)        a[i]=(d[i]-d[i-1])/2;    a[1]=d[1];    for(int i=2;i<n;i++)        a[1]+=a[i];    int det=x[0];    for(int i=1;i<=n;i++)        det-=a[i]*(i-1);    v.clear();    for(int i=1;i<n;i++)        if(a[i])v.push_back(make_pair(a[i],i));    while(det<0)    {        v.push_back(make_pair(-50,0));        det+=50;    }    while(det>0)    {        v.push_back(make_pair(min(det,50),0));        det-=min(det,50);    }    if((int)v.size()==0)printf("0");    else if((int)v.size()==1)    {        if(v[0].first<0)printf("(0-");        if(!v[0].second)            printf("%d",abs(v[0].first));        else            printf("(%d*abs((t-%d)))",abs(v[0].first),v[0].second);        if(v[0].first<0)printf(")");    }    else    {        for(int i=1;i<(int)v.size();i++)            printf("(");        for(int i=0;i<(int)v.size();i++)        {            if(i==0)            {                if(v[i].first<0)printf("((0-%d)*abs((t-%d)))",abs(v[i].first),v[i].second);                else printf("(%d*abs((t-%d)))",abs(v[i].first),v[i].second);            }            else            {                printf("%s",(v[i].first<0 ? "-" : "+"));                if(!v[i].second)                    printf("%d",abs(v[i].first));                else                    printf("(%d*abs((t-%d)))",abs(v[i].first),v[i].second);                printf(")");            }        }    }    printf("\n");}int main(){    int n;    scanf("%d",&n);    for(int i=0;i<n;i++)        scanf("%d%d%*d",&x[i],&y[i]);    if(n==1)    {        printf("%d\n%d\n",x[0],y[0]);    }    else    {        for(int i=0;i<n;i++)        {            if(x[i]&1)x[i]--;            if(y[i]&1)y[i]--;        }        work(n);        memcpy(x,y,sizeof(y));        work(n);    }    return 0;}

Happy Tree Party(树链剖分)

题目链接:

http://codeforces.com/contest/593/problem/D

解题思路:

Consider the problem ignoring the second typed requests. We note that in the column where all the numbers on the edges of  >  1 maximum number of assignments to  before x will turn into 0 is not exceeds 64. Indeed, if all the Rv = 2, the number of operations can be assessed as log2(x). Hang the tree for some top and call it the root.

Learn how to solve the problem, provided that for every v Rv > 1 and no requests of the second type. For each vertex except the root, we have identified it as the ancestor of the neighbor closest to the root. Suppose we had a request of the first type from the top a to b vertices with original number x. We divide the road into two vertical parts, one of which is close to the root, while the other moves away. We find all the edges in this way. To do this, we calculate the depth of each node to the root of the distance. Now we will go up in parallel to the tree of the two peaks, until he met a total. If in the course of the recovery, we have been more than 64 edges, in the substitutions  we get x = 0 and we can at the current step to stop the algorithm search. Thus, we make no more than O(log(x)) operations.

Let`s turn to the problem, where Rv > 0. We note that our previous solution in this case can work for O(n). Since the passage of the edge with Rv = 1 our value does not change. We reduce this problem to the above consideration. Compress the graph, that is, remove all single edges. To do this, run by dfs root and will keep the deepest edge on the path from the root to the top with Rv > 1.

Let us remember that we have had requests to reduce Rv. We maintain the closest ancestor of Pv c RPv > 1. We use the idea of compression paths. When answer to a request of the first type will be recalculated Pv. We introduce a recursive function F(v). Which returns the v, if Rv > 1, otherwise perform the assignment of Pv = F(Pv) and returns F(Pv). Each edge we will remove 1 times, so in total the call of all functions F(v) running O(n).

Final time is O(logx) on request of the first type and O(1) an average of request of the second type.

算法思想:

以后补上。

AC代码:


0 0