• 10.23模拟赛


    U14259 叉叉

    题目描述

    现在有一个字符串,每个字母出现的次数均为偶数。
    接下来我们把第一次出现的字母a和第二次出现的a
    连一条线,第三次出现的和四次出现的字母a连一条线,
    第五次出现的和六次出现的字母a连一条线..
    .对其他25个字母也做同样的操作。
    现在我们想知道有多少对连线交叉。
    交叉的定义为一个连线的端点在另外一个连线的内部,
    另外一个端点在外部。
    下图是一个例子,共有三对连线交叉(我们连线的时候,只能从字符串上方经过)。

    输入输出格式

    输入格式:

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

    输出格式:

    一个整数,表示答案。

    输入输出样例

    输入样例#1:

    abaazooabz

    输出样例#1:

    3

    说明

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

    #include<iostream>
    #include<cstring>
    #include<string>
    #include<cstdio>
    using namespace std;
    
    struct list{
        int pos,next,ji;
    }l[10000005];
    int head[27];
    int num;
    int f[27];
    int ans;
    int a[27];
    int b[27];
    
    void add(int sum,int pos){
        l[++num].pos=pos;
        l[num].next=head[sum];
        head[sum]=num;
        if(!f[sum]){f[sum]=1;l[num].ji=true;}
        else {f[sum]=0;l[num].ji=false;}
    }
    
    string str;    
        
    int main(){
    //    freopen("a.in","r",stdin);
    //    freopen("b.out","w",stdout);
        cin>>str;
        for(int i=0;i<str.size();++i){
            add(str[i]-'a',i);
        }
        for(int i=str.size()-1;i>-1;--i){
            int sum=str[i]-'a';
            if(head[sum]!=i+1)continue;
            a[sum]=head[sum];
            b[sum]=l[head[sum]].next;
            for(int j=a[sum]-2;j>b[sum]-1;--j){
                int sumbre=str[j]-'a';
                if(j>head[sumbre]-1)continue;
                if(l[j+1].ji)continue;
                a[sumbre]=j+1;
                b[sumbre]=l[j+1].next;
                if(b[sumbre]<b[sum])ans++;
            }
            head[sum]=l[l[head[sum]].next].next;
        }
        cout<<ans;
        return 0;
    }
    

    做法

    链表
    感觉我这是一个O(n2)的程序,但是肯定不是O(n2)因为跑过了而且还很快
    Lqz大佬和我都是用链表做的,他说是严格O(n)的,我的程序和它不太一样
    我真的感觉这是一个(O(n^2))
    但是至少(10^6)能完成
    正解前缀和……
    还有写树状数组和线段树的反正做法很多

    U14261 跳跳虎回家

    题目描述

    跳跳虎在外⾯出去玩忘了时间,现在他需要在最短的时间内赶回家。
    跳跳虎所在的世界可以抽象成⼀个含有 个点的图(点编号从 到 ),
    跳跳虎现在在 号点,跳跳虎的家在 号点。
    图上⼀共有 条单向边,通过每条边有固定的时间花费。
    同时,还存在若⼲个单向传送通道,传送通道也有其时间花费。
    传送通道⼀般来说⽐普通的道路更快,但是跳跳虎最多只能使⽤ 次。
    跳跳虎想知道他回到家的最⼩时间消耗是多少。

    输入输出格式

    输入格式:

    第一行4个整数(n,m,q,k)
    ( n表示点数,m表示普通道路的数量, q表示传送通道的数量,
    k表示跳跳虎最多使k次传送通道)
    接下来 n行每3 个整数a,b,c ,表示有1条从a到b,时间花费为c的普通道路
    接下来 q每3个整数a,b,c,表示有1条从a到b,时间花费为c的传送道路
    输出格式:
    输出一行1个整数表示最少时间消耗,如果没法回到家输出-1。

    输入输出样例

    输入样例#1:

    5 5 2 1
    1 2 1
    1 3 2
    2 4 2
    3 4 3
    4 5 4
    1 4 1
    2 5 1

    输出样例#1:

    2

    说明

    对于30%的数据, 1 ≤ n ≤ 500,0 ≤ m,q ≤ 2000,k = 0
    对于另外30%的数据, 1 ≤ n ≤ 500,0 ≤ m,q ≤ 2000,k = 1
    对于100%的数据 1 ≤ n ≤ 500,0 ≤ m,q ≤ 2000,0 ≤ k ≤ (10^9)

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define N 200005
    using namespace std;
    
    int a,b,c;
    int n,m,q,k;
    
    struct edge{
        int v,next,cost;
    }E[N],e[N];
    int h1[N],h2[N];
    int t1,t2;
    
    struct node{
        int k,c;
        bool operator < (const node & s)const{
            return c<s.c;return k<s.k;
        }
    };
    
    void add(int a,int b,int c){
        E[++t1].v=b;
        E[t1].cost=c;
        E[t1].next=h1[a];
        h1[a]=t1;
    }
    
    void push(int a,int b,int c){
        e[++t2].v=b;
        e[t2].cost=c;
        e[t2].next=h2[a];
        h2[a]=t2;
    }
    
    queue<int>que;
    bool vis[N];
    int dis[N][2];
    //priority_queue<node>Q[N];
    
    void SPFA(){
        que.push(1);
        vis[1]=1;
        memset(dis,0x3f,sizeof(dis));
        dis[1][0]=0;
        while(!que.empty()){
            int sss=que.front();
            que.pop();
            vis[sss]=0;
            for(int i=h1[sss];i;i=E[i].next){
                int v=E[i].v;
                if(dis[v][0]>dis[sss][0]+E[i].cost){
                    dis[v][0]=dis[sss][0]+E[i].cost;
                    if(!vis[v]){
                        que.push(v);
                        vis[v]=1;
                    }
                }
                if(dis[v][1]>dis[sss][1]+E[i].cost){
                    dis[v][1]=dis[sss][1]+E[i].cost;
                    if(!vis[v]){
                        que.push(v);
                        vis[v]=1;
                    }
                }
            }
            for(int i=h2[sss];i;i=e[i].next){
                int v=e[i].v;
                if(dis[v][1]>dis[sss][0]+e[i].cost){
                    dis[v][1]=dis[sss][0]+e[i].cost;
                    if(!vis[v]){
                        que.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
    }
    
    void spfa(){
        que.push(1);
        vis[1]=1;
        memset(dis,0x3f,sizeof(dis));
        dis[1][0]=0;
        while(!que.empty()){
            int sss=que.front();
            que.pop();
            vis[sss]=0;
            for(int i=h1[sss];i;i=E[i].next){
                int v=E[i].v;
                if(dis[v][0]>dis[sss][0]+E[i].cost){
                    dis[v][0]=dis[sss][0]+E[i].cost;
                    if(!vis[v]){
                        que.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
    }
    
    void Spfa(){
        que.push(1);
        vis[1]=1;
        memset(dis,0x3f,sizeof(dis));
        dis[1][0]=0;
        while(!que.empty()){
            int sss=que.front();
            que.pop();
            vis[sss]=0;
            for(int i=h1[sss];i;i=E[i].next){
                int v=E[i].v;
                if(dis[v][0]>dis[sss][0]+E[i].cost){
                    dis[v][0]=dis[sss][0]+E[i].cost;
                    if(!vis[v]){
                        que.push(v);
                        vis[v]=1;
                    }
                }
            }
            for(int i=h2[sss];i;i=e[i].next){
                int v=e[i].v;
                if(dis[v][0]>dis[sss][0]+e[i].cost){
                    dis[v][0]=dis[sss][0]+e[i].cost;
                    if(!vis[v]){
                        que.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
    }
    
    int main(){
    //    freopen("move.in","r",stdin);
    //    freopen("move.out","w",stdout);
        cin>>n>>m>>q>>k;
        for(int i=1;i<=m;++i){
            cin>>a>>b>>c;
            add(a,b,c);
        }
        for(int i=1;i<=q;++i){
            cin>>a>>b>>c;
            push(a,b,c);
        }
        if(k==1)SPFA();
        else if(!k)spfa();
        else Spfa();
        int ans=0x3f3f3f3f;
        for(int i=0;i<=1;++i)
            ans=min(ans,dis[n][i]);
        cout<<ans;
        return 0;
    }
    

    数据奇水
    本来以为k肯定有小于边数大于1的数据
    但是没有……所以乱搞(数据分治)就搞过去了
    正解做法应该是dp
    交上去的是个数据分治,因为30分部分分有个地方变量名写错了所以只得了45分

    U14263 秀秀和哺噜国(cut)

    题目描述

    哺噜国里有!个城市,有的城市之间有高速公路相连。在最开始时,哺噜国里有n− 条高
    速公路,且任意两座城市之间都存在一条由高速公路组成的通路。
    由于高速公路的维护成本很高, 为了减少哺噜国的财政支出,将更多的钱用来哺育小哺噜,
    秀秀女王决定关闭一些高速公路。 但是为了保证哺噜国居民的正常生活,
    不能关闭太多的高速公路,要保证每个城市通过高速公路与至少$个城市(包括自己)相连。

    在得到了秀秀女王的指令后,交通部长华华决定先进行预调研。
    华华想知道在满足每个城市都可以与至少$个城市相连的前提下,
    有多少种关闭高速公路的方案(可以一条也不关) 。两种方案不同,
    当且仅当存在一条高速公路在一个方案中被关闭,
    而在另外一个方案中没有被关闭。 由于方案数可能很大,
    你只需输出不同方案数对786433取模后的结果即可。
    其中786433 =
    (2^{17})+ 1。

    输入输出格式

    输入格式:

    从文件cut.in 中读入数据。
    输入第一行,包含两个正整数n,k。
    接下来的n − 1行,每行包含两个正整数a和b,
    表示城市a和城市b之间有一条高速公路相
    连。

    输出格式:

    输出文件到cut.out 中。
    输出一个非负整数,表示所求方案数对786433 取模后的结果。

    输入输出样例

    输入样例#1:

    5 2
    1 2
    2 3
    3 4
    4 5

    输出样例#1:

    3

    【样例 1 解释】

    三种方案分别为:
    一条高速公路也不关闭;
    关闭城市2和城市3之间的高速公路;
    关闭城市3和城市4之间的高速公路。

    输入样例#2:

    10 2
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    3 10
    5 8
    6 9

    输出样例#2:

    12

    【子任务】

    对于20%的数据:! ≤ 20;
    另有30%的数据:! ≤ 100;
    另有10%的数据:$ ≤ 100;
    另有20%的数据:! ≤ 1000;
    对于100%的数据:! ≤ 5000,$ ≤ !。

    说明

    空间限制:512MB

    听说是个树形dp但是不会
    233
    题解大人说:
    我们令dp[i][j]表示以i为根且当前联通块大小为k的方案总数,
    特别的,dp[i][0]表示割点当前点与其父亲是棵树的方案总数。
    对于u的一个孩子v可以得到转移方程dp[u][j+k]=dp[u][j]*dp[v][k]
    另外$$dp[u][0]=sum_{j=0}^{k} dp[u][j]$$
    这样乍看是n^3的,有一个技巧可以做到n^2即每次dp时,
    只枚举当前u所在子树的大小,每当枚举到它的其中孩子时,
    当前u所在子树的大小加上它孩子为根的子树的大小。
    可以理解为每一个点对只被枚举到一次。
    最后答案即为dp[root][0]

    #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]);
    	return 0;
    }
    
  • 相关阅读:
    弹出层layer的使用
    SQL Server SQL分页查询
    C#过滤html标签
    SQLServer ForXmlPath应用
    js调用soapWebService服务
    MediaWiki使用指南
    阿里云金融云服务器配置
    VS无法启动 IISExpress web 服务器
    mysql服务突然丢失解决方案
    [k8s]通过openssl生成证书
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/7716758.html
Copyright © 2020-2023  润新知