Codeforces Round #261 (Div. 2)(树状数组,dp,dfs构造序列)

来源:互联网 发布:苏联打阿富汗知乎 编辑:程序博客网 时间:2024/06/06 17:59

C. Pashmak and Buses

Recently Pashmak has been employed in a transportation company. The company hask buses and has a contract with a school which hasn students. The school planned to take the students tod different places for d days (each day in one place). Each day the company provides all the buses for the trip. Pashmak has to arrange the students in the buses. He wants to arrange the students in a way that no two students become close friends. In his ridiculous idea, two students will become close friends if and only if they are in the same buses for alld days.

Please help Pashmak with his weird idea. Assume that each bus has an unlimited capacity.

Input

The first line of input contains three space-separated integers n, k, d (1 ≤ n, d ≤ 1000; 1 ≤ k ≤ 109).

Output

If there is no valid arrangement just print -1. Otherwise printd lines, in each of them printn integers. The j-th integer of thei-th line shows which bus thej-th student has to take on the i-th day. You can assume that the buses are numbered from1 tok.

Sample test(s)
Input
3 2 2
Output
1 1 2 1 2 1 
Input
3 2 1
Output
-1
Note

Note that two students become close friends only if they share a bus each day. But the bus they share can differ from day to day.

题意:n个学生,k辆车,d天,要求学生两两之间不能在同一辆车一起d天,问怎么一个安排的方案
思路:对于每个学生而言,在d天的坐车情况,只要不和其他人重复即可,这样进行dfs构造序列,如果能构造出n个不同序列,就是可以的,如果不能就输出-1

#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=1010;int ans[maxn][maxn],tmp[maxn];int n,k,d,cnt;void dfs(int x){    if(cnt>n)return;    if(x>d)    {        for(int i=1;i<=d;i++)            ans[i][cnt]=tmp[i];        cnt++;        return ;    }    for(int i=1;i<=min(k,1000);i++)    {        tmp[x]=i;        dfs(x+1);    }}int main(){    while(scanf("%d%d%d",&n,&k,&d)!=EOF)    {        memset(ans,0,sizeof(ans));        cnt=1;        dfs(1);        if(cnt<=n)printf("-1\n");        else        {            for(int i=1;i<=d;i++)            {                for(int j=1;j<=n;j++)                    printf("%d ",ans[i][j]);                printf("\n");            }        }    }    return 0;}

D. Pashmak and Parmida's problem

Parmida is a clever girl and she wants to participate in Olympiads this year. Of course she wants her partner to be clever too (although he's not)! Parmida has prepared the following test problem for Pashmak.

There is a sequence a that consists of n integers a1, a2, ..., an. Let's denotef(l, r, x) the number of indicesk such that: l ≤ k ≤ r andak = x. His task is to calculate the number of pairs of indiciesi, j(1 ≤ i < j ≤ n) such thatf(1, i, ai) > f(j, n, aj).

Help Pashmak with the test.

Input

The first line of the input contains an integer n(1 ≤ n ≤ 106). The second line containsn space-separated integers a1, a2, ..., an(1 ≤ ai ≤ 109).

Output

Print a single integer — the answer to the problem.

Sample test(s)
Input
71 2 1 1 2 2 1
Output
8
Input
31 1 1
Output
1
Input
51 2 3 4 5
Output
0
思路:先预处理出f(1,i,ai),f(j,n,aj),然后就是求s1[i]>s[j]&&i<j的和,这个就跟求逆序数是一样的,树状数组就可以了

#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=1000010;typedef long long LL;int n,a[maxn],cnt1[maxn],cnt2[maxn];map<int,int> m;struct BIT{    int sum[maxn];    void clear(){memset(sum,0,sizeof(sum));};    int lowbit(int x){return x&(-x);}    void update(int x,int val)    {        while(x<=n)        {            sum[x]+=val;            x+=lowbit(x);        }    }    int getsum(int x)    {        int ans=0;        while(x>0)        {            ans+=sum[x];            x-=lowbit(x);        }        return ans;    }}tree;void solve(){    LL ans=0;    tree.clear();    for(int i=n;i>=1;i--)    {        ans+=tree.getsum(max(cnt1[i]-1,0));        if(cnt2[i])tree.update(cnt2[i],1);    }    cout<<ans<<endl;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)scanf("%d",&a[i]);    for(int i=1;i<=n;i++)    {        m[a[i]]++;        cnt1[i]=m[a[i]];    }    m.clear();    for(int i=n;i>0;i--)    {        m[a[i]]++;        cnt2[i]=m[a[i]];    }    solve();    return 0;}

E. Pashmak and Graph

Pashmak's homework is a problem about graphs. Although he always tries to do his homework completely, he can't solve this problem. As you know, he's really weak at graph theory; so try to help him in solving the problem.

You are given a weighted directed graph with n vertices andm edges. You need to find a path (perhaps, non-simple) with maximum number of edges, such that the weights of the edges increase along the path. In other words, each edge of the path must have strictly greater weight than the previous edge in the path.

Help Pashmak, print the number of edges in the required path.

Input

The first line contains two integers n,m (2 ≤ n ≤ 3·105; 1 ≤ m ≤ min(n·(n - 1), 3·105)). Then,m lines follows. The i-th line contains three space separated integers: ui, vi, wi (1 ≤ ui, vi ≤ n; 1 ≤ wi ≤ 105) which indicates that there's a directed edge with weight wi from vertexui to vertexvi.

It's guaranteed that the graph doesn't contain self-loops and multiple edges.

Output

Print a single integer — the answer to the problem.

Sample test(s)
Input
3 31 2 12 3 13 1 1
Output
1
Input
3 31 2 12 3 23 1 3
Output
3
Input
6 71 2 13 2 52 4 22 5 22 6 95 4 34 3 4
Output
6
Note

In the first sample the maximum trail can be any of this trails: .

In the second sample the maximum trail is .

In the third sample the maximum trail is .

题意:给出一个有向带权值的图,要求出最长递增链路的长度。也就是当前边的权值要大于前一条边的。

思路:先对边按权值排序,然后dp,edge表示边的dp,node表示点的dp,然后进行更新

#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=300010;struct A{    int x,y,w;    bool operator<(const A & a)const    {        return w<a.w;    }}e[maxn];int edge[maxn],node[maxn];int n,m;int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)        scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);    sort(e+1,e+m+1);    for(int i=1;i<=m;i++)    {        int j=i;        while(j<=m&&e[j].w==e[i].w)        {            int x=e[j].x;            edge[j]=max(edge[j],node[x]+1);            j++;        }        j=i;        while(j<=m&&e[j].w==e[i].w)        {            int y=e[j].y;            node[y]=max(node[y],edge[j]);            j++;        }        i=j-1;    }    int ans=0;    for(int i=1;i<=m;i++)ans=max(ans,edge[i]);    printf("%d\n",ans);    return 0;}




0 0