• 2022杭电多校第三场题解


    2022杭电多校第三场

    在这里插入图片描述

    Cyber Language(模拟)

    题意
    将一个句子中每个单词的第一个字母大写。

    分析
    读入一行字符串可用getlinefgets,对每个字符串遍历所有字符,如果一个字符是小写字母且前一个字符是空格或者它是第一个字符,那么把它转大写输出,也可使用stringstream

    AC代码

    写法一

    int main()
    {
    	int t;
    	cin>>t;
    	string s;
    	getline(cin,s);
    	while(t--)
    	{
    		getline(cin,s);
    		stringstream ss(s);
    		string str;
    		while(ss>>str)
    		{
    			cout<<(char)toupper(str[0]);
    		}
    		cout<<endl;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    写法二

    #include
    #include
    const int N=1000005;
    int Case,n,i;char s[N];
    int main(){
      fgets(s,N,stdin);
      sscanf(s,"%d",&Case);
      while(Case--){
        fgets(s,N,stdin);
        n=strlen(s);
        for(i=0;i<n;i++)
          if(s[i]>='a'&&s[i]<='z')
            if(!i||(i>0&&s[i-1]==' '))
              putchar(s[i]-'a'+'A');
        puts("");
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    Package Delivery(贪心)

    题意
    邮局里有 n n n个包裹,每个包裹可在 [ l , r ] [l,r] [l,r]时间段内取。小Q每次最多取 k k k件包裹,每天可以去多次,求小Q去邮局取完所有快递的最小次数。

    分析
    首先,对于 r r r最小的区间,在第 r r r天取不会使答案变差,并且在第 r r r天必须去取快递。由于每次可以取 k k k件包裹,对于第 r r r天可以取的包裹优先选择右端点最小的包裹,右端点大的包裹有更大的选择空间。因此确定贪心策略:每次选择未取包裹中右端点最小的作为取货时间,将这一天可以取的包裹放入优先队列,优先选择右端点小的包裹。时间复杂度 O ( n l o g ( n ) ) O(nlog(n)) O(nlog(n))

    AC代码

    const int N=1e5+10;
    struct node {
    	int l,r;
    }p[N];
    int ql[N],qr[N],vis[N];
    int n,k;
    
    bool cmpl(int x,int y) { return p[x].l<p[y].l; }
    bool cmpr(int x,int y) { return p[x].r<p[y].r; }
    
    int main()
    {
    	int T;
    	cin>>T;
    	while(T--)
    	{
    		cin>>n>>k;
    		for(int i=1;i<=n;i++) cin>>p[i].l>>p[i].r;
    		for(int i=1;i<=n;i++) ql[i]=qr[i]=i,vis[i]=0;
    		sort(ql+1,ql+n+1,cmpl);
    		sort(qr+1,qr+n+1,cmpr);
    		priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> q;
    		int j=1;
    		int ans=0;
    		for(int i=1;i<=n;i++)
    		{
    			if(vis[qr[i]]) continue;
    			while(j<=n&&p[ql[j]].l<=p[qr[i]].r)
    			{
    				q.push({p[ql[j]].r,ql[j]});
    				j++;
    			}
    			ans++;
    			int x=k;
    			while(x--)
    			{
    				if(q.empty()) break;
    				vis[q.top().second]=1;
    				q.pop();
    			}
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    Two Permutations(DP)

    题意
    给定两个1~n的全排列P和Q,再给定一个长度为2n的序列S,每次从P和Q的最左端选一个元素放在一个初始为空的序列R的最右端,问有多少种方案使得R=S

    分析
    线性DP, f [ i ] [ 0 / 1 ] f[i][0/1] f[i][0/1]表示 R R R的第 i i i位和 P / Q P/Q P/Q匹配的方案数。注意到 P P P Q Q Q都是全排列,1~n每个元素在 P P P Q Q Q中只出现一次,可以在DP之前记录每个元素出现的位置。时间复杂度 O ( n ) O(n) O(n)

    AC代码

    #include 
    #define endl '\n'
    using namespace std;
    typedef long long ll;
    const int mod=998244353;
    const int N=3e5+10;
    int a[N],b[N],pos1[N],pos2[N],c[N<<1];
    ll f[N<<1][2];
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(0); cout.tie(0);
    	int T;
    	cin>>T;
    	while(T--)
    	{
    		int n;
    		cin>>n;
    		for(int i=1;i<=n;i++) cin>>a[i],pos1[a[i]]=i;
    		for(int i=1;i<=n;i++) cin>>b[i],pos2[b[i]]=i;
    		for(int i=1;i<=2*n;i++) cin>>c[i];
    		for(int i=1;i<=2*n;i++) f[i][0]=f[i][1]=0;
    		f[1][0]=(c[1]==a[1]);
    		f[1][1]=(c[1]==b[1]);
    		for(int i=2;i<=2*n;i++)
    		{
    			int x=pos1[c[i]];
    			int y=pos2[c[i]];
    			if(x+n>=i)
    			{
    				if(c[i-1]==a[x-1]) f[i][0]+=f[i-1][0];
    				if(c[i-1]==b[i-x]) f[i][0]+=f[i-1][1];
    			}
    			if(y+n>=i)
    			{
    				if(c[i-1]==b[y-1]) f[i][1]+=f[i-1][1];
    				if(c[i-1]==a[i-y]) f[i][1]+=f[i-1][0];
    			}
    			f[i][0]%=mod;
    			f[i][1]%=mod;
    		}
    		cout<<(f[2*n][0]+f[2*n][1])%mod<<endl;
    	}
    	
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
  • 相关阅读:
    网络连接删除了怎么弄好
    Hive用户中文使用手册系列(三)
    Go 项目配置文件的定义和读取
    Go开发工具GoLand V2022.2 来了——Go 工作区重大升级
    轻量化Backbone | ShuffleNet+ViT结合让ViT也能有ShuffleNet轻量化的优秀能力
    图片破损打不开如何修复?一招轻松恢复损坏图片!
    初露头角!Walrus入选服贸会“数智影响力”数字化转型创新案例
    计算机学院第一周语法组及算法组作业
    【javaEE】多线程进阶(Part2 JUC、线程安全、死锁)
    【Python 实战基础】Pandas如何从字符串中解析某一数据,并统计多于一次的该数据
  • 原文地址:https://blog.csdn.net/weixin_46155777/article/details/126389225