Codeforces Round #266 (Div. 2)(good)

B. Wonder Room

The start of the new academic year brought about the problem of accommodation students into dormitories. One of such dormitories has a a × b square meter wonder room. The caretaker wants to accommodate exactly n students there. But the law says that there must be at least 6 square meters per student in a room (that is, the room for n students must have the area of at least 6n square meters). The caretaker can enlarge any (possibly both) side of the room by an arbitrary positive integer of meters. Help him change the room so as all n students could live in it and the total area of the room was as small as possible.

Input

The first line contains three space-separated integers n, a and b (1 ≤ n, a, b ≤ 109) — the number of students and the sizes of the room.

Output

Print three integers s, a1 and b1 (a ≤ a1b ≤ b1) — the final area of the room and its sizes. If there are multiple optimal solutions, print any of them.

Sample test(s)
Input
3 3 5
Output
18
3 6
Input
2 4 4
Output
16
4 4

题意:找到两个a,b,比给出的大,并且乘积大于6*n,并且乘积尽量小

思路:枚举1~sqrt(n),然后算出另外的数,看是不是符合条件

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const long long INF=1000000000000000100;
typedef long long LL;
long long n,a,b;
int main()
{
    cin>>n>>a>>b;
    if(a*b>=6*n){cout<<a*b<<endl<<a<<" "<<b<<endl;return 0;}
    n*=6;
    bool flag=0;
    if(a>b) swap(a, b), flag=1;
    LL ans=INF,xx,yy;
    for(long long i=1; i<=n; ++i) {
        long long x=i, y=(n+x-1)/x;
        if(x>y) break;
        if(x<a) x=a;
        if(y<b) y=b;
        if(x*y<ans) {
            ans=x*y, xx=x, yy=y;
        }
    }
    if(flag) swap(xx, yy);
    printf("%I64d\n%I64d %I64d\n", ans, xx, yy);
    return 0;
}

C. Number of Ways

You've got array a[1], a[2], ..., a[n], consisting of n integers. Count the number of ways to split all the elements of the array into three contiguous parts so that the sum of elements in each part is the same.

More formally, you need to find the number of such pairs of indices i, j (2 ≤ i ≤ j ≤ n - 1), that .

Input

The first line contains integer n (1 ≤ n ≤ 5·105), showing how many numbers are in the array. The second line contains n integers a[1], a[2], ..., a[n] (|a[i]| ≤  109) — the elements of array a.

Output

Print a single integer — the number of ways to split the array into three parts with the same sum.

Sample test(s)
Input
5
1 2 3 0 3
Output
2
Input
4
0 1 -1 0
Output
1
Input
2
4 1
Output
0

注意long long

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=500010;
typedef long long LL;
int a[maxn],n;
LL sum[maxn];
LL cnt[maxn];
int main()
{
    scanf("%d",&n);
    LL add=0;
    memset(sum,0,sizeof(sum));
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        add+=a[i];
        sum[i]=sum[i-1]+a[i];
    }
    if(add%3){printf("0\n");return 0;}
    cnt[n]=(sum[n]-sum[n-1]==add/3?1:0);
    for(int i=n-1;i>=1;i--)
    {
        if(sum[n]-sum[i-1]==add/3)cnt[i]=cnt[i+1]+1;
        else cnt[i]=cnt[i+1];
    }
    LL ans=0;
    for(int i=1;i<=n;i++)
    {
        if(sum[i]==add/3)
            ans+=cnt[i+2];
    }
    cout<<ans<<endl;
    return 0;
}

D. Increase Sequence

Peter has a sequence of integers a1, a2, ..., an. Peter wants all numbers in the sequence to equal h. He can perform the operation of "adding one on the segment [l, r]": add one to all elements of the sequence with indices from l to r (inclusive). At that, Peter never chooses any element as the beginning of the segment twice. Similarly, Peter never chooses any element as the end of the segment twice. In other words, for any two segments [l1, r1] and [l2, r2], where Peter added one, the following inequalities hold: l1 ≠ l2 and r1 ≠ r2.

How many distinct ways are there to make all numbers in the sequence equal h? Print this number of ways modulo 1000000007 (109 + 7). Two ways are considered distinct if one of them has a segment that isn't in the other way.

Input

The first line contains two integers n, h (1 ≤ n, h ≤ 2000). The next line contains n integers a1, a2, ..., an (0 ≤ ai ≤ 2000).

Output

Print a single integer — the answer to the problem modulo 1000000007 (109 + 7).

Sample test(s)
Input
3 2
1 1 1
Output
4
Input
5 1
1 1 1 1 1
Output
1
Input
4 3
3 2 1 1
Output
0

思路(转载):

先把a数组变成需要加多少变成h。

然后在对a数组前向差分得出b数组。

cnt:标记到当前位置,有几个l没有和r匹配

如果b[i]==1:

说明当前位置有一个l,cnt++;

如果b[i]==0:

1,当前位置什么都没有

2,当前位置有一个l,一个r。

因为有一个l,所以cnt++.

有一个r,所以总数*=cnt,cnt--;

相当于总数*=(cnt+1);

如果b[i]==-1:

当前位置有一个r,所以总数*=cnt,cnt--;

如果b[i]不等于上面的三种情况,说明无解!

#include<stdio.h>  
#include<iostream>  
#include<stdlib.h>  
#include<string.h>  
#include<algorithm>  
#include<vector>  
#include<math.h>  
#include<queue>  
#include<stack>  
#include<map>  
#pragma comment(linker, "/STACK:1024000000,1024000000")  
using namespace std;  
#define maxn 550000  
#define mod 1000000007  
#define LL __int64  
LL a[maxn];  
LL b[maxn];  
int main()  
{  
    int n,h;  
    while(~scanf("%d%d",&n,&h))  
    {  
        for(int i=1;i<=n;i++)scanf("%I64d",&a[i]);  
        for(int i=1;i<=n;i++)a[i]=h-a[i];  
        for(int i=1;i<=n+1;i++)  
        {  
            b[i]=a[i]-a[i-1];  
        }  
        LL ans=1;  
        LL cnt=0;  
        for(int i=1;i<=n+1;i++)  
        {  
            if(b[i]==1)  
            {  
                cnt++;  
            }  
            else if(b[i]==-1)  
            {  
                ans=ans*(cnt)%mod;  
                cnt--;  
            }  
            else if(b[i]==0)  
            {  
                ans=ans*(cnt+1)%mod;  
            }  
            else  
            {  
                ans=0;break;  
            }  
            ans=ans%mod;  
        }  
        cout<<ans<<endl;  
    }  
    return 0;  
}  

E. Information Graph

There are n employees working in company "X" (let's number them from 1 to n for convenience). Initially the employees didn't have any relationships among each other. On each of m next days one of the following events took place:

  • either employee y became the boss of employee x (at that, employee x didn't have a boss before);
  • or employee x gets a packet of documents and signs them; then he gives the packet to his boss. The boss signs the documents and gives them to his boss and so on (the last person to sign the documents sends them to the archive);
  • or comes a request of type "determine whether employee x signs certain documents".

Your task is to write a program that will, given the events, answer the queries of the described type. At that, it is guaranteed that throughout the whole working time the company didn't have cyclic dependencies.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 105) — the number of employees and the number of events.

Each of the next m lines contains the description of one event (the events are given in the chronological order). The first number of the line determines the type of event t (1 ≤ t ≤ 3).

  • If t = 1, then next follow two integers x and y (1 ≤ x, y ≤ n) — numbers of the company employees. It is guaranteed that employee x doesn't have the boss currently.
  • If t = 2, then next follow integer x (1 ≤ x ≤ n) — the number of the employee who got a document packet.
  • If t = 3, then next follow two integers x and i (1 ≤ x ≤ n; 1 ≤ i ≤ [number of packets that have already been given]) — the employee and the number of the document packet for which you need to find out information. The document packets are numbered started from 1 in the chronological order.

It is guaranteed that the input has at least one query of the third type.

Output

For each query of the third type print "YES" if the employee signed the document package and "NO" otherwise. Print all the words without the quotes.

Sample test(s)
Input
4 9
1 4 3
2 4
3 3 1
1 2 3
2 2
3 1 2
1 3 1
2 2
3 1 3
Output
YES
NO
YES
思路:将每个文件移动的范围处理出来,然后对于每次询问,将询问拆成两个标记,假设查询x是否浏览过第k号文件,第k号文件的范围为u-v,那么在最后dfs时,遍历到x,判断是否经过u;遍历到v时,判断是否经过x。如果两个都满足,则是YES。相当于对这个文件的头和尾进行标记,对于询问的点,如果在文件的范围内,那么经过头尾时都会被标记一次。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=100010;
int N,M,pra[maxn],num[maxn];
bool vis[maxn];
vector<int> g[maxn];
vector<pair<int,int> > q[maxn];
vector<pair<int,int> > file;
int find(int x)
{
    if(pra[x]==x)return x;
    return pra[x]=find(pra[x]);
}
void dfs(int u)
{
    vis[u]=1;
    int len=g[u].size();
    for(int i=0;i<len;i++)
        dfs(g[u][i]);
    len=q[u].size();
    for(int i=0;i<len;i++)
    {
        if(vis[q[u][i].first])
            num[q[u][i].second]++;
    }
    vis[u]=0;
}
int main()
{
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++)pra[i]=i;
    int cnt=0;
    for(int i=1;i<=M;i++)
    {
        int t,x,y;
        scanf("%d%d",&t,&x);
        if(t==1)
        {
            scanf("%d",&y);
            g[y].push_back(x);
            int px=find(x),py=find(y);
            if(px!=py)pra[px]=py;
        }
        else if(t==2)
        {
            file.push_back(make_pair(find(x),x));
        }
        else if(t==3)
        {
            scanf("%d",&y);
            q[x].push_back(make_pair(file[y-1].first,cnt));
            q[file[y-1].second].push_back(make_pair(x,cnt));
            cnt++;
        }
    }
    memset(vis,0,sizeof(vis));
    memset(num,0,sizeof(num));
    for(int i=1;i<=N;i++)
        if(pra[i]==i)dfs(i);
    for(int i=0;i<cnt;i++)
        if(num[i]==2)printf("YES\n");
        else printf("NO\n");
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值