zoukankan      html  css  js  c++  java
  • cf #617 C-E2

    acm萌新,以后在这个博客更新和记录一些题目吧

    本来以为这场div3能上分,结果t3卡住了,然后t4明明很简单但只扫了一眼......

    t3一直在想双指针,思路太沙雕正解就是用一个map<pair<int,int>,int>记录最后到达当前位置的是第几个字符,想法就是如果现在到达的位置之前也到达过,那么这段就可以删掉。然后使得可以删掉的长度大小最小,并记录对应的posl,posr。然后一些细节也弄了挺久,位置各种+1 -1的错...还是太菜了

    #include<bits/stdc++.h>
    using namespace std;
    const int inf=200000+10;
    map<pair<int,int>,int> mp; //***
    int main()
    {
    	string s;
    	int t,i,j,k,n,len,f,posl,posr;
    	//freopen("617c.txt","r",stdin);
    	cin>>t;
    	while (t--)
    	  {
    	  	int min=inf;
    	  	pair<int,int> p=make_pair(0,0);//***
    	  	cin>>n;mp.clear();
    	  	cin>>s;len=s.length();
    	  	posl=-1;posr=-1;
    		mp[{p.first,p.second}]=0;
    	  	for (i=0;i<len;i++)
    	  	  {
    	  	  	if (s[i]=='U') p.second++;
    	  	  	if (s[i]=='D') p.second--;  	  	  	  	
    	  	  	if (s[i]=='R') p.first++;
    	  	  	if (s[i]=='L') p.first--;
    	  	  	if (mp[{p.first,p.second}]!=0||(p.first==0&&p.second==0))
    	  	  	  {
    	  	  	  	k=i-mp[{p.first,p.second}]+1;
    	  	  	  	if (k<min)
    	  	  	  	  {
    	  	  	  	  	min=k;
    	  	  	  	  	posl=mp[{p.first,p.second}]+1;
    	  	  	  	  	posr=i+1;
    				  }
    			  }
    			mp[{p.first,p.second}]=i+1;
    		  }
    		if (posl==-1&&posr==-1) cout<<-1<<endl;
    		else cout<<posl<<' '<<posr<<endl;
     	  }
     	//fclose(stdin);
     	return 0;
    }
    

      

    D题其实比较水,对于当前的怪物,算最少要使用技能多少次才能拿分,然后排个序就完了

    算使用技能次数的时候也弄错了一些小细节......

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=200+10;
    int h[maxn],cnt[maxn];
    int main()
    {
        int n,a,b,k,i,j,ans,t,y;
        scanf("%d%d%d%d",&n,&a,&b,&k);
        for (i=1;i<=n;i++) scanf("%d",&h[i]);
        memset(cnt,0,sizeof(cnt));
        for (i=1;i<=n;i++)
          {
            if (h[i]<=a) continue;
            t=h[i]%(a+b);
            if (t>0&&t<=a) continue;
            if (t==0)
              {
                if (b%a==0) cnt[i]=b/a;else cnt[i]=b/a+1;
                continue;
              }
            if (t%a==0) cnt[i]=t/a-1;else cnt[i]=t/a;
          }
        //for (i=1;i<=n;i++) printf("%d ",cnt[i]);
        sort(cnt+1,cnt+n+1);
        i=j=0;
        while (j<=k)
          {
            i++;if (i>n) break;
            j+=cnt[i];
          }
        ans=i-1;printf("%d
    ",ans);
        return 0;
    }
    

      

    E1和E2

    先看E2吧。结合题解有了自己的一点想法。首先找出原序列的最长严格下降子序列,设长度为m,那么就至少需要m种颜色了。如果颜色<=m-1种,这m个数必定有两个数同色,次序一定无法交换,所以最后序列肯定不是单调不降的。那么有m种颜色就可以划分了。因为根据dilworth定理(emmm不太会证,但是知道这个结论),原序列可以划分成m个不下降子序列,然后给每个不下降子序列染成相同的颜色就行了。其实这道题的本质就是最少能划分成多少个不下降子序列

     

    有两个有点巧的地方:

    一是虽然n<=100000,看上去直接求个lis复杂度不太行,然后nlogn的lis保存方案也好烦。但是每个元素的范围只有1-26,所以可以用pos[i](1<=i<=26)保存i出现的最后一个位置,因为相同的元素,位置越靠后的,这个位置能连的下降子序列就越长。这样时间复杂度只有O(26n)。二是染色的时候只要染成下降子序列dp数组的元素值就行了(这个一开始没想到)。因为dp数组的最大值为m,然后如果元素相同,就一定是单调不降的。这样刚好划分成m个不下降子序列

    代码超级短:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=200+10;
    int dp[maxn],pos[30],a[maxn]; //pos[i]:字符i(1-26)的最后一个位置 
    string s;
    int i,j,k,t,n;
    
    int main()
    {
    	std::ios::sync_with_stdio(false);
    	cin>>n>>s;
    	for (i=0;i<n;i++)
    	  a[i+1]=s[i]-'a'+1;
    	memset(dp,0,sizeof(dp));
    	memset(pos,0,sizeof(pos));
    	dp[1]=1;pos[a[1]]=1;
    	for (i=2;i<=n;i++){
    		dp[i]=1;
    		for (j=1;j<=26;j++)
    		  if (pos[j]>0&&j>a[i]) dp[i]=max(dp[i],dp[pos[j]]+1);
    		pos[a[i]]=i;
    	}
    	int ans=0;
    	for (i=1;i<=n;i++) ans=max(dp[i],ans);
    	cout<<ans<<endl;
    	for (i=1;i<=n-1;i++) cout<<dp[i]<<' ';
    	cout<<dp[n]<<endl;
    	return 0;
    }
    

      

    然后看E1。E1就是问能不能染成两种颜色,当然可以用E2的方法做,而且E1的n<200,直接求下降子序列就行了。但是题解给出了一个贪心的方法感觉挺神奇的,脑补一下感觉挺对的:设已经有两个子序列,如果一个新的元素>=子序列一的末位,就把它连到一后面,如果>=二的末位就连到二后面,否则无解......

    #include<bits/stdc++.h>
    using namespace std;
    string s,ans;
    
    int main()
    {
        int i,j,n,f;
        cin>>n>>s;
        char last1,last2;
        last1='a';last2='a';
        ans=""; f=0;
        for (i=0;i<n;i++)
          {
          	if (s[i]<last1&&s[i]<last2){
          		cout<<"NO"<<endl;f=1;
          		break;
    		  }
    		if (s[i]>=last1){
    			ans+='0';
    			last1=s[i];
    		}
    		else if (s[i]>=last2){
    			ans+='1';
    			last2=s[i];
    		}
    	  }
    	if (f==0){
    		cout<<"YES"<<endl;
    	    cout<<ans<<endl;
    	}
    	return 0;
     } 
    

      

  • 相关阅读:
    sql server等待类型
    进程死锁运行状态、进程阻塞、死锁监控
    sql server安装教程(2008 R2,图形界面安装/命令提示符安装即静默安装/无人值守安装)
    (3.7)存储引擎--索引的结构与分类
    (3.6)存储引擎--文件与数据的结构
    (3.5)存储引擎--日志
    (3.4)存储引擎--内存
    (3.3)存储引擎--数据读写
    PhoneGap and Titanium
    touch
  • 原文地址:https://www.cnblogs.com/edmunds/p/12288502.html
Copyright © 2011-2022 走看看