Codeforces Round #345 (Div. 2)

D题:直接滑窗,枚举转折点,滑动结束点。水题啊水题。。。。

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))
#define PII pair<int,int>

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;

int n,a,b,T;
char s[maxn],t[maxn];
int look[maxn];

int solve(int dir)
{
    if(dir) reverse(s+2,s+n+1);
    REP(i,1,n) look[i]=s[i]==‘w‘?b+1:1;
    int ans=0;
    int cost=look[1],cnt=1;
    int x=1,y=n+1;
    /// find the last y
    while(y>1){
        y--;
        if(y==1){
            y++;break;
        }
        cost+=a+look[y];
        cnt++;
        if(cost>T){
            cnt--,cost-=a+look[y],y++;
            break;
        }
    }
    //cout<<"cnt="<<cnt<<" cost="<<cost<<" T="<<T<<endl;
    if(cost<=T) ans=max(ans,cnt);
    /// solve
    for(x=1;;){
        if(x+1==y) break;
        x++;
        cost+=2*a+look[x];
        cnt++;
        while(y<=n&&cost>T){
            cost-=look[y]+a;
            cnt--;
            y++;
        }
        if(cost<=T) ans=max(ans,cnt);
    }
    return ans;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    while(cin>>n>>a>>b>>T){
        scanf("%s",s+1);
        int ans=0;
        REP(i,0,1) ans=max(ans,solve(i));
        cout<<ans<<endl;
    }
    return 0;
}

/**
4 2 3 10
wwhw

5 2 4 13
hhwhh

5 2 4 1000
hhwhh

3 1 100 10
whw

*/

E题:贪心+并查集。

将所有数拿出来从小到大排序,按顺序填进去,第一个肯定是填1,接着用如果当前要填的数为x,看x的所在行和所在列,要填的x必然大于等于所在行和所在列的最大值,如果大于的话很好处理,取最大值+1就可以了,关键在于等于的时候。这里用并查集维护,将在同一行或同一列相等的数用并查集连通起来,那么每次只要需要更新的时候只要更新并查集的祖先就可以了,反正无论找哪个都会找到它的祖先。而如果某个数在同行同列没有相等的,那么它的祖先就是它自己了。现在问题就解决了,每添加一个数,检查同行同列有没有相等的,如果有更新并查集的祖先或它,并将它和祖先连起来,如果没有直接更新就行了。分四种情况代码会比较清晰一些。

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))
#define PII pair<int,int>

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;

int n,m;
int a[maxn];
PII b[maxn];int N;
int fa[maxn];
int val[maxn];
int rid[maxn],cid[maxn];/// 行最大值的位置,列最大值的位置

int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    while(cin>>n>>m){
        REP(i,1,n) REP(j,1,m) scanf("%d",&a[(i-1)*m+j]);
        REP(i,1,n) fa[i]=i;
        N=n*m;
        REP(i,1,N) b[i]={a[i],i};
        sort(b+1,b+N+1);
        REP(i,1,N) fa[i]=i;
        MS0(val);
        MS0(rid);MS0(cid);
        int p1=b[1].second;
        int r1=(p1-1)/m+1,c1=p1%m;
        if(c1==0) c1=m;
        val[p1]=1;
        rid[r1]=cid[c1]=p1;
        REP(i,2,N){
            int p=b[i].second;
            int r=(p-1)/m+1,c=p%m;
            if(c==0) c=m;
            int x=find(rid[r]),y=find(cid[c]);
            if(a[p]>a[x]&&a[p]>a[y]){
                rid[r]=cid[c]=p;
                val[p]=max(val[x],val[y])+1;
            }
            else if(a[p]>a[x]&&a[p]==a[y]){
                rid[r]=p;
                val[p]=max(val[x]+1,val[y]);
                fa[y]=p;
            }
            else if(a[p]==a[x]&&a[p]>a[y]){
                cid[c]=p;
                val[p]=max(val[x],val[y]+1);
                fa[x]=p;
            }
            else{
                rid[r]=cid[c]=p;
                val[p]=max(val[x],val[y]);
                fa[x]=p;fa[y]=p;
            }
        }
        REP(i,1,n){
            REP(j,1,m){
                int x=find((i-1)*m+j);
                printf("%d ",val[x]);
            }
            puts("");
        }
    }
    return 0;
}

/**
2 2
1 2
3 4

4 3
20 10 30
50 40 30
50 60 70
90 80 70

1 1
1
2 2
2 2
2 2

4 3
7 8 8
5 1 4
3 2 8
4 5 4

*/

时间: 2024-12-15 04:36:18

Codeforces Round #345 (Div. 2)的相关文章

cf之路,1,Codeforces Round #345 (Div. 2)

 cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅.....       其实这个应该是昨天就写完的,不过没时间了,就留到了今天.. 地址:http://codeforces.com/contest/651/problem/A A. Joysticks time limit per test 1 second memory limit per test 256

Codeforces Round #345 (Div. 2)C. Watchmen(想法题)

传送门 Description Watchmen are in a danger and Doctor Manhattan together with his friend Daniel Dreiberg should warn them as soon as possible. There are n watchmen on a plane, the i-th watchman is located at point (xi, yi). They need to arrange a plan,

Codeforces Round #345 (Div. 2) D 细节题

这个题的意思是给你n张首尾相接的照片, 当前照片在1, 每次只能转移一个单位, 转移时间为a, 照片有可能颠倒, 将照片摆正需要的时间为b, 看照片的时间为1, 想要看尽可能多的照片, 问这个数量是多少, 我们可以预处理查看每张照片需要的时间, 然后枚举从左边看需要的时间, 从右边看需要的时间, 二分从另外一边看需要的时间即可, 代码如下: #include <cstdio> #include <algorithm> #include <cstring> using n

Codeforces Round #345 Div.1 D.Zip-line 动态最长上升子序列

题意概述: 给出一个长度为N的序列和M组询问,问假设把某个位置的值改成另一个给出的值之后,序列的最长上升子序列的长度. N,M<=400000. 分析: 考虑某个位置的值改动后这个位置和最长上升子序列(lis)的关系: 1.这个位置包含在lis中(这种情况答案可能+1,可计算经过这个点的lis来等效决策). 2.这个位置不包含在lis中,那么需要看是否任意的lis都经过这个位置.如果是的话此决策的结果在原来长度基础上-1,否则就等于原来的长度. 有了大体思路,接下来想想维护. 任务1:对于任意位

A Joysticks (Codeforces Round 345 (Div 2) )

Friends are going to play console. They have two joysticks and only one charger for them. Initially first joystick is charged at a1 percent and second one is charged at a2 percent. You can connect charger to a joystick only at the beginning of each m

Codeforces Round #279 (Div. 2) ABCD

Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name     A Team Olympiad standard input/output 1 s, 256 MB  x2377 B Queue standard input/output 2 s, 256 MB  x1250 C Hacking Cypher standard input/output 1 s, 256 MB  x740 D Chocolate standard input/

Codeforces Round #506 (Div. 3) 题解

Codeforces Round #506 (Div. 3) 题目总链接:https://codeforces.com/contest/1029 A. Many Equal Substrings 题意: 给出长度为n的字符串,然后要求你添加一些字符,使得有k个这样的字符串. 题解: 直接暴力吧...一个指针从1开始,另一个从2开始,逐一比较看是否相同:如果不同,第一个指针继续回到1,第二个指针从3开始...就这么一直重复.最后如果第二个指针能够顺利到最后一位,那么记录当前的第一个指针,把他后面的

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿