9.26模拟赛

怎么说,确实50pts垫底。可是并不是不会。。。

T1:

【题目描述】
二哥想知道在一段时期内,一共有多少个交易日。期货交易日的限定如下:
周六、周日不能交易;
元旦期间(1 月 1 日)不能交易;
五一劳动节期间(5月 1日至 3 日)不能交易;
十一国庆节期间(10月 1日至 7 日)不能交易;
没有在上述要求中提到的日期均可交易。

【输入数据】
第一行有一个整数 n,表示一共有 n 组数据。
每组数据都有一行,是两个用空格分开的日期,分别为开始日期和结束日期。
日期格式为 YYYY-MM-DD(比如 2010-11-11)。
数据保证开始日期不晚于结束日期。

【输出数据】
输出共 n 行,每行一个整数,对应于一组数据。
每组数据需要输出在指定日期区间内,共有多少个交易日。
区间的开始和结束日期也算在内(如果是交易日的话)。

【数据规模】

对于所有数据:n≤365。对于 30%的数据: 日期范围从 2010-11-23至 2012-12-21;
对于 100%的数据:日期范围从 1900-01-01至 9999-12-31;
已知 1900-01-01是星期一。

大模拟。

忘了考虑365组数据,结果直接暴力找的。。。TLE到30

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
int ans,t;
struct node{
    int c[4];
}st,nd,now;
char s[30];
char ch;
int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int sum[13];
void clear(){
    ans=0;
}
node in(){
    int len=strlen(s+1);
    int cnt=0;
    node ret;
    for(int i=1;i<=len;i++){
        if(s[i]>'0'&&s[i]<='9'){
            int sum=0;cnt++;
            while(i<=len&&s[i]>='0'&&s[i]<='9'){
                sum=sum*10+s[i]-'0';i++;
            }
            ret.c[cnt]=sum;
            i--;
        }        
    }
    return ret;
}
bool run(int x){
    if((x%4==0&&x%100!=0)||(x%400==0)) return true;
    return false;
}
bool lim(node lp,node kk){
    if(lp.c[1]<kk.c[1]) return true;
    if(lp.c[1]>kk.c[1]) return false;
    
    if(lp.c[2]<kk.c[2]) return true;
    if(lp.c[2]>kk.c[2]) return false;
    
    if(lp.c[3]<=kk.c[3]) return true;
    if(lp.c[3]>kk.c[3]) return false;
    return false;
}
int main(){
    //freopen("stock.in","r",stdin);
    //freopen("stock.out","w",stdout);
    scanf("%d",&t);
    for(int i=1;i<=12;i++) sum[i]=sum[i-1]+day[i];
    while(t--){
        clear();
        
        scanf("%s",s+1);
        st=in();
        scanf("%s",s+1);
        nd=in();
        int xing=1;
        int tot=0;
        for(int i=1900;i<st.c[1];i++){
            if((i%4==0&&i%100!=0)||(i%400==0)){
                tot+=366;
            }
            else tot+=365;
        }
        xing=1+tot%7;//has st.year's xingqi
        tot=0;
        for(int i=1;i<st.c[2];i++){
            if(i==2){
                if(run(st.c[1])) tot+=29;
                else tot+=28;
            } 
            else tot+=day[i];
        }        
        xing=xing+tot%7;//has st.month's xingqi
        if(xing>7) xing-=7;
        
        tot=0;
        for(int i=1;i<st.c[3];i++){
            tot++;
        }
        xing=xing+tot%7;//has st.day's xingqi
        if(xing>7) xing-=7;
        
        //cout<<" xing "<<xing<<endl; 
        
        now=st;
        if(nd.c[1]-st.c[1]!=0){
            node up;up.c[1]=now.c[1],up.c[2]=12,up.c[3]=31;
            
            while(lim(now,up)){
                if(xing!=6&&xing!=7){
                    if(now.c[2]!=1||now.c[3]!=1){
                        if(now.c[2]!=10||now.c[3]>7){
                            if(now.c[2]!=5||now.c[3]>3){
                                ans++;
                            }
                        }
                    }
                }
                xing++;if(xing==8) xing=1;
                
                now.c[3]++;
                if(now.c[3]>day[now.c[2]]){
                    if(now.c[2]==2){
                        if(!run(now.c[1])) {
                            now.c[3]=1,now.c[2]++;
                        }
                        else if(now.c[3]==30){
                            now.c[3]=1,now.c[2]++;
                        }
                    }
                    else {
                        now.c[3]=1,now.c[2]++;
                    }
                }
                
                if(now.c[2]>12) now.c[1]++,now.c[2]=1;
            }
            
            int i=now.c[1];
            for(;i<nd.c[1];i++){
                int tot=365+run(i);
                ans+=8-xing-(xing<=6)-(xing<=7);
                if(xing!=6&&xing!=7) ans--;//01-01
                int day51=xing+(sum[4]+run(i))%7;
                
                if(day51!=6&&day51!=7) ans--;
                day51++;if(day51==8) day51=1;
                
                if(day51!=6&&day51!=7) ans--;
                day51++;if(day51==8) day51=1;
                
                if(day51!=6&&day51!=7) ans--;
                day51++;if(day51==8) day51=1;//05-01
                
                ans-=5;//10-01
                
                tot-=8-xing;
                ans+=5*(tot/7);
                int re=tot%7;
                //xing=1;
                ans+=re-(re==6);
                xing=re+1;
                
                
            }
            
            now.c[1]=i,now.c[2]=now.c[3]=1;
        }
        
        while(lim(now,nd)){
            if(xing!=6&&xing!=7){
                if(now.c[2]!=1||now.c[3]!=1){
                    if(now.c[2]!=10||now.c[3]>7){
                        if(now.c[2]!=5||now.c[3]>3){
                            ans++;
                        }
                    }
                }
            }
            xing++;if(xing==8) xing=1;
            
            now.c[3]++;
            if(now.c[3]>day[now.c[2]]){
                if(now.c[2]==2){
                    if(!run(now.c[1])) {
                        now.c[3]=1,now.c[2]++;
                    }
                    else if(now.c[3]==30){
                        now.c[3]=1,now.c[2]++;
                    }
                }
                else {
                    now.c[3]=1,now.c[2]++;
                }
            }
            
            if(now.c[2]>12) now.c[1]++,now.c[2]=1;
        }
        printf("%d\n",ans);
    }
    return 0;
}
T1

T2:

【题目描述】
Bob看见一个字符串,它包含许多不同的字符,这些字符被标记成不同的数字,但同一个字
符串中每个字符能在字符串出现最多 10 次。Bob不喜欢这个字符串,因为它包含重复段:一段长
为 x 的字符串的重复段是一个长为 2x 的字符串,且其前半个字符串与后半个字符串每个字符对
应相同。Bob 开始从该字符串中删除所有重复段,他按以下规则进行:如果可能,Bob 选择最短
的重复段,如果它不唯一,他选择最左边的那个,并删除该重复段的左半边和它左侧的所有东西。
现在给出 Bob看见的字符串,找出其被 Bob按上述规则删除所有重复子串之后的样子。

【输入】
输入文件第一行包含整数 n,表示字符串的长度。
下面一行包含 n 个由空格隔开的在 0 到 10^9范围内的数字,数字表示字符串中的字符。
数据保证每个字符在字符串中最多出现 10 次。

【输出】
输出文件的第一行包含 Bob删除后遗留的子串的长度。
第二行输出 Bob 按照上述方式删除所有重复段后遗留的子串(每个字符由一个空格隔开)。

机智地在不需要至少10个字符的这个条件下,写出了优于常人的正解。。。

然而,题目要求是:

1.输出剩余长度

2.输出剩余的字符串。

说!!

为什么忘了第一个???

真·AC100变爆零

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<map>
using namespace std;
typedef long long ll;
const int N=100000+5;
int n;
int a[N];
map<int,int>mp;
int nxt[N],b[N];
int tot;
int R;
int main(){
    //freopen("dor.in","r",stdin);
    //freopen("dor.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int j=n;j>=1;j--){
        nxt[j]=mp[a[j]];
        if(nxt[j]) b[j]=nxt[j]-j;
        mp[a[j]]=j;
    }
    for(int i=1;i<=n;i++){
        if(b[i]==0) continue;
        int cnt=0,v=b[i];
        while(i<=n&&b[i]==v&&cnt<v){
            cnt++;i++;
        }
        i--;
        if(cnt==v){
            R=max(R,i);
        }
    }
    printf("%d\n",n-(R+1)+1);
    for(int i=R+1;i<=n;i++){
        printf("%d ",a[i]);
    }
    return 0;
}
T2

T3:

【问题描述】
为了绿化乡村,H村积极响应号召,开始种树了。
H村里有n幢房屋,这些屋子的排列顺序很有特点,在一条直线上。于是方便起见,我们给它
们标上1~n。树就种在房子前面的空地上。
同时,村民们向村长提出了m个意见,每个意见都是按如下格式:希望第Li个房子到第Ri个房
子的房前至少有Ci棵树。
因为每个房屋前的空地面积有限,所以每个房屋前最多只能种Ki棵树。
村长希望在满足村民全部要求的同时,种最少的树以节约资金。现在请你编程帮助村长解决
这个问题。

【数据范围】
对于30%的数据, 0<n≤100,0<m≤100,Ki=1;
对于50%的数据, 0<n≤2000,0<m≤5000,0<Ki≤100;
对于70%的数据, 0<n≤50000,0<m≤100000,0<Ki≤1000;
对于100%的数据,0<n≤500000,0<m≤500000,0<Ki≤5000。

其实很裸的差分约束了。

但是,由于对于这种类型题目,和差分约束实在不熟悉。结果没有想出来。

对于ai-bi>=ci这种,而且又有区间,而且对于区间和有一个限制

直接前缀和做差啊!!全都有了!!

就是想不到?!?!

差分约束一般都是前缀和做差。——ywy_c_asm

确实,反正是没做过其他的。。。

然后对于差分约束的理解:

1.如果跑最短路,那么得到的dis是<=源点到每个点距离L的最大解。

为什么?首先最短路,一定小于等于L,其次,由于刚好满足最短的时候,本来可以人为再小一些的,也可能满足条件。

但是,连得边权就是这样,怎么会再少一些距离呢?

所以,刚好满足最短的时候,就停止了,所以一定是所有合法解中最大的一个。

2.如果跑最长路,得到的是>=L的最小解。

证明同理。

这个题,一看,sum[i]>=0而且要最小。

直接列式子,然后spfa最长路即可。

(dij不行,有负权边)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=500000+5;
const int inf=0x3f3f3f3f;
void rd(int &x){
    char ch;
    while(!isdigit(ch=getchar()));
    for(x=(ch^'0');isdigit(ch=getchar());x=x*10+(ch^'0'));
}
struct node{
    int nxt,to;
    int val;
}e[4*N];
int hd[N],cnt;
int n,m;
void add(int x,int y,int z){
    e[++cnt].nxt=hd[x];
    e[cnt].to=y;
    e[cnt].val=z;
    hd[x]=cnt;
}
int dis[N];
int q[N*10],l,r;
bool vis[N];
void spfa(){
    for(int i=0;i<=n;i++) dis[i]=-inf;
    dis[n+1]=0;
    l=1,r=0;
    q[++r]=n+1;
    vis[n+1]=1;
    while(l<=r){
        int x=q[l++];
        vis[x]=0;
        //cout<<x<<endl;
        for(int i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(dis[y]<dis[x]+e[i].val){
                dis[y]=dis[x]+e[i].val;
                if(!vis[y]){
                    vis[y]=1;
                    q[++r]=y;
                }
            }
        }
    }
}
int main(){
    rd(n);rd(m);
    int k,c;
    int l,r;
    for(int i=1;i<=n;i++){
        //scanf("%lld",&k);
        rd(k);
        add(i,i-1,-k);
        add(i-1,i,0);
        add(n+1,i,0);
    }
    add(n+1,0,0);
    for(int i=1;i<=m;i++){
        //scanf("%d%d%lld",&l,&r,&c);
        rd(l);rd(r);rd(c);
        add(l-1,r,c);
    }
    spfa();
    printf("%d",dis[n]);
    return 0;
}
T3

猜你喜欢

转载自www.cnblogs.com/Miracevin/p/9708223.html