2017-10-23 NOIP模拟赛

叉叉

题目描述

现在有一个字符串,每个字母出现的次数均为偶数。接下来我们把第一次出现的字母a和第二次出现的a连一条线,第三次出现的和四次出现的字母a连一条线,第五次出现的和六次出现的字母a连一条线...对其他25个字母也做同样的操作。

现在我们想知道有多少对连线交叉。交叉的定义为一个连线的端点在另外一个连线的内部,另外一个端点在外部。

下图是一个例子,共有三对连线交叉(我们连线的时候,只能从字符串上方经过)。

输入格式

一行一个字符串。保证字符串均由小写字母组成,且每个字母出现次数为偶数次。

输出格式

一个整数,表示答案。

样例输入

abaazooabz

样例输出

3

数据范围

对于30% 的数据,字符串长度不超过50。

对于100% 的数据,字符串长度不超过100,000。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int top,ans,cnt[27],pos[27],num[27],a[100010];
char s[100010];
int main(){
    freopen("cross.in","r",stdin);freopen("cross.out","w",stdout);
    //freopen("Cola.txt","r",stdin);
    scanf("%s",s);
    int len=strlen(s);
    memset(pos,0x3f,sizeof(pos));
    for(int i=0;i<len;i++){
        int now=s[i]-'a';
        num[now]++;
        if(num[now]%2==0){
            ans+=cnt[now];
            for(int j=0;j<26;j++){
                if(j==now)continue;
                if(pos[j]<pos[now])cnt[j]--;
            }
            pos[now]=0x7fffffff;
            cnt[pos[now]]=0;
        }
        else {
            a[top]=now;
            pos[now]=top;
            cnt[now]=0;
            top++;
            for(int j=0;j<26;j++){
                if(j==now)continue;
                if(pos[j]<pos[now])cnt[j]++;
            }
        }
    }
    printf("%d",ans);
}
100分 栈模拟

 跳跳虎回家

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#define maxn 501
using namespace std;
int n,m,p,k,num,head[maxn],f[501][2001];
struct node{int to,pre,v,mark;}e[2000+2001];
struct Node{
    int id,cnt,dis;
    bool operator < (const Node b)const{
        return dis>b.dis;
    }
};
Node make_Node(int id,int cnt,int dis){
    Node res;
    res.id=id;res.cnt=cnt;res.dis=dis;
    return res;
}
void Insert(int from,int to,int v,int mark){
    e[++num].to=to;
    e[num].v=v;
    e[num].mark=mark;
    e[num].pre=head[from];
    head[from]=num;
}
priority_queue<Node>q;
void Dij(){
    q.push(make_Node(1,0,0));
    memset(f,0x3f,sizeof(f));f[1][0]=0;
    while(!q.empty()){
        Node now=q.top();int point=now.id,d=now.dis,c=now.cnt;
        q.pop();
        for(int i=head[point];i;i=e[i].pre){
            int to=e[i].to;
            if(e[i].mark==0&&f[to][c]>f[point][c]+e[i].v){
                f[to][c]=f[point][c]+e[i].v;
                q.push(make_Node(to,c,f[to][c]));
            }
            if(c<k&&e[i].mark==1&&f[to][c+1]>f[point][c]+e[i].v){
                f[to][c+1]=f[point][c]+e[i].v;
                q.push(make_Node(to,c+1,f[to][c+1]));
            }
        }
    }
}
int main(){
    //freopen("Cola.in","r",stdin);
    freopen("move.in","r",stdin);freopen("move.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&p,&k);
    int x,y,z;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        Insert(x,y,z,0);
    }
    for(int i=1;i<=p;i++){
        scanf("%d%d%d",&x,&y,&z);
        Insert(x,y,z,1);
    }
    Dij();
    int ans=0x7fffffff;
    for(int i=0;i<=min(k,p);i++){
        ans=min(ans,f[n][i]);
    }
    if(ans>20000000){puts("-1");return 0;}
    printf("%d",ans);
}
80分 Dij+dp
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define maxn 5010
using namespace std;
int n,m,p,k,l,r,mid;
int num,head[maxn],num2,head2[maxn],dis[maxn];
bool vis[maxn],ok[maxn],flag;
struct node{
    int to,pre,v,mark;
}e[maxn],e2[maxn];
void Insert(int from,int to,int v,int mark){
    e[++num].to=to;
    e[num].v=v;
    e[num].pre=head[from];
    e[num].mark=mark;
    head[from]=num;
}
void Insert2(int from,int to,int v,int mark){
    e2[++num2].to=to;
    e2[num2].v=v;
    e2[num2].pre=head2[from];
    e2[num2].mark=mark;
    head2[from]=num2;
}
void Spfa(){
    queue<int>q;
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    vis[1]=1;dis[1]=0;
    q.push(1);
    while(!q.empty()){
        int now=q.front();q.pop();vis[now]=0;
        for(int i=head[now];i;i=e[i].pre){
            if(e[i].mark)continue;
            int to=e[i].to;
            if(dis[to]>dis[now]+e[i].v){
                dis[to]=dis[now]+e[i].v;
                if(!vis[to])vis[to]=1,q.push(to);
            }
        }
    }
}
void dfs(int now,int d,int t){
    if(t>k)return;
    if(d>mid)return;
    if(now==n){flag=1;return;}
    if(flag)return;
    for(int i=head[now];i;i=e[i].pre){
        int to=e[i].to;
        if(!ok[to])continue;
        if(!vis[to]){
            vis[to]=1;
            dfs(to,d+e[i].v,t+e[i].mark);
            vis[to]=0;
        }
    }
}
bool check(){
    flag=0;
    memset(vis,0,sizeof(vis));
    vis[1]=1;
    dfs(1,0,0);
    if(flag)return 1;
    else return 0;
}
void bfs(){
    queue<int>q;
    q.push(n);ok[n]=1;
    while(!q.empty()){
        int now=q.front();q.pop();
        for(int i=head2[now];i;i=e2[i].pre){
            int to=e2[i].to;
            if(!ok[to]){
                ok[to]=1;
                q.push(to);
            }
        }
    }
}
int main(){
    //freopen("Cola.txt","r",stdin);
    freopen("move.in","r",stdin);freopen("move.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&p,&k);
    int x,y,z;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        Insert(x,y,z,0);
        Insert2(y,x,z,0);
        r+=z;
    }
    for(int j=1;j<=p;j++){
        scanf("%d%d%d",&x,&y,&z);
        Insert(x,y,z,1);
        Insert2(y,x,z,1);
        r+=z;
    }
    if(k==0){
        Spfa();
        if(dis[n]>=20000000){puts("-1");return 0;}
        printf("%d",dis[n]);return 0;
    }
    else {
        bfs();
        if(!ok[1]){puts("-1");return 0;}
        int ans=-1;
        while(l<=r){
            mid=(l+r)>>1;
            if(check())ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d",ans);
    }
}
95分 二分答案
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#define maxn 501
using namespace std;
int n,m,p,k,num,head[maxn],f[501][2001];
bool vis[maxn][2001];
struct node{int to,pre,v,mark;}e[2001+2001];
struct Node{
    int id,cnt,dis;
    bool operator < (const Node b)const{
        return dis>b.dis;
    }
};
Node make_Node(int id,int cnt,int dis){
    Node res;
    res.id=id;res.cnt=cnt;res.dis=dis;
    return res;
}
void Insert(int from,int to,int v,int mark){
    e[++num].to=to;
    e[num].v=v;
    e[num].mark=mark;
    e[num].pre=head[from];
    head[from]=num;
}
priority_queue<Node>q;
void Dij(){
    q.push(make_Node(1,0,0));
    memset(f,0x3f,sizeof(f));f[1][0]=0;
    while(!q.empty()){
        Node now=q.top();int point=now.id,d=now.dis,c=now.cnt;
        if(point==n)break;//非常有用的一句话 
        q.pop();
        for(int i=head[point];i;i=e[i].pre){
            int to=e[i].to;
            if(e[i].mark==0&&f[to][c]>f[point][c]+e[i].v){
                f[to][c]=f[point][c]+e[i].v;
                q.push(make_Node(to,c,f[to][c]));
            }
            if(c<k&&e[i].mark==1&&f[to][c+1]>f[point][c]+e[i].v){
                f[to][c+1]=f[point][c]+e[i].v;
                q.push(make_Node(to,c+1,f[to][c+1]));
            }
        }
    }
}
int main(){
    //freopen("Cola.in","r",stdin);
    freopen("move.in","r",stdin);freopen("move.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&p,&k);
    int x,y,z;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        Insert(x,y,z,0);
    }
    for(int i=1;i<=p;i++){
        scanf("%d%d%d",&x,&y,&z);
        Insert(x,y,z,1);
    }
    Dij();
    int ans=0x7fffffff;
    for(int i=0;i<=min(k,p);i++){
        ans=min(ans,f[n][i]);
    }
    if(ans>20000000){puts("-1");return 0;}
    printf("%d",ans);
}
100分 Dij+dp(一个有用的优化)

秀秀和哺噜国

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 5010
#define mod 786433
using namespace std;
int n,k,num,head[maxn],fal[maxn],sz[maxn],ans,can[maxn],c;
bool vis[maxn],v[maxn];
struct node{
    int to,pre,v;
}e[maxn];
void Insert(int from,int to,int id){
    e[id].to=to;
    e[id].pre=head[from];
    head[from]=id;
    num=max(num,id);
}
void Dfs(int now,int father){
    sz[now]=1;
    for(int i=head[now];i;i=e[i].pre){
        int to=e[i].to;
        if(to==father)continue;
        fal[to]=i;
        Dfs(to,now);
        sz[now]+=sz[to];
    }
}
int bfs(int x){
    int res=1;
    queue<int>q;
    q.push(x);
    vis[x]=1;
    while(!q.empty()){
        int now=q.front();q.pop();
        for(int i=head[now];i;i=e[i].pre){
            if(e[i].v!=0)continue;
            int to=e[i].to;
            if(!vis[to]){
                vis[to]=1;
                q.push(to);
                res++;
            }
        }
    }
    return res;
}
bool check(){
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            if(bfs(i)<k)return 0;
        }
    }
    return 1;
}
void dfs(int pos){
    if(pos>c){
        //for(int i=1;i<=num;i++)cout<<i<<' '<<e[i].v<<endl;cout<<endl;
        if(check()){
            ans++;
            if(ans>=mod)ans-=mod;
        }
        return;
    }
    dfs(pos+1);
    int w=(can[pos]>=n?(can[pos]-n+1):(can[pos]+n-1));
    e[can[pos]].v=1;
    e[w].v=1;
    dfs(pos+1);
    e[can[pos]].v=0;
    e[w].v=0;
}
int main(){
    //freopen("Cola.in","r",stdin);
    freopen("cut.in","r",stdin);freopen("cut.out","w",stdout);
    scanf("%d%d",&n,&k);
    int x,y;
    for(int i=1;i<n;i++){
        scanf("%d%d",&x,&y);
        Insert(x,y,i);Insert(y,x,i+n-1);
    }
    Dfs(1,0);
    int sum=0;
    for(int i=1;i<=n;i++)
        if(sz[i]<k){
            //e[fal[i]].v=1;
            int w=(fal[i]>=n?fal[i]-n+1:fal[i]+n-1);
            //e[w].v=1;
            v[fal[i]]=v[w]=1;
            sum++;
        }
    for(int i=1;i<=num;i++){
        if(v[i]==0){
            can[++c]=i;
            int w=(i>=n?i-n+1:i+n-1);
            v[w]=1;
            v[i]=1;
        }
    }
    dfs(1);
    printf("%d",ans);
    return 0;
}
20分 暴力
#include<cstdio>
#include<cstdlib>
#define N 5555
#define M 786433
using namespace std;
typedef long long LL;
struct edge
{
    int t,n;
}e[N*2];
LL h[N],size[N],f[N][N],g[N],cnt[N];
int n,K,tote;
void add(int u,int v)
{
    e[++tote].t=v;
    e[tote].n=h[u];
    h[u]=tote;
    return ;
}
void dfs(int u,int fa)
{
    size[u]++; f[u][1]=1;
    for (int i=h[u];i;i=e[i].n)
    {
        int v=e[i].t;
        if (v==fa) continue;
        dfs(v,u);
        for (int j=1;j<=size[u]+size[v];j++) g[j]=0;
        for (int j=1;j<=size[u];j++) g[j]=cnt[v]*f[u][j]%M;
        for (int j=1;j<=size[u];j++)
        for (int k=1;k<=size[v];k++) g[j+k]=(g[j+k]+f[u][j]*f[v][k]%M)%M;
        for (int j=1;j<=size[u]+size[v];j++) f[u][j]=g[j];
        size[u]+=size[v];
    }
    for (int i=K;i<=size[u];i++) cnt[u]=(cnt[u]+f[u][i])%M;
    return ;
}
int main()
{
    freopen("cut.in","r",stdin);
    freopen("cut.out","w",stdout);
    scanf("%d %d",&n,&K);
    for (int i=1;i<n;i++)
    {
        int u,v;
        scanf("%d %d",&u,&v);
        add(u,v); add(v,u);
    }
    dfs(1,1);
    printf("%d
",cnt[1]);
    fclose(stdin);
    fclose(stdout);
    return 0;
}
100分 树形背包
原文地址:https://www.cnblogs.com/thmyl/p/7716451.html