Cf 98 Div.2
2012-02-16 16:54
411 查看
又ak了一场 div2。。。
A题
给定一个CCPPCCPPCCCCCPPPP这样的只有C,P的串,从左到右,每次最多取5个字符,每次取的字符必须相同,问最少要取多少次。
我的代码比较短:
每次循环定个初始位置,以该位置的下一个位置开始for循环4次.
B题
给定一个序列n<= 5000,每个元素大小介于1到n之间,问至少需要改变多少个元素才能使序列中的元素是两两不同即1到n每个数字各出现一次。
超水,统计没有出现的数字的个数。
C题
给定最多100000个区间,保证坐标x,y都是没有重复的。问有多少个区间是被包含了。
水。。。
按x排升序,然后对于每个区间,看前面已经查询过的区间的y的最大值,这个用一个变量保存就可以了。
鄙视,数组开小了,看成了10000,另外,貌似sort直接对pair排序是默认以first作为第一关键字的。
D题
给定长度为n的字符串,n<=500,然后是k,要求把串划分为 不多于k个段,可以是1,2,3..k段,要求每段是回文串。 同时为了保证是回文串,需要进行必要的修改字符操作,要求输出最小的修改次数,即最后的结果串,段段之间用+号连接,如果多个答案,随意输出一个。
如:
answer:
我的做法是dp,为了方便,我的字符串从1开始到n作为索引,dp[i][j]: [1,i] 划分为 j段的最小修改次数,显然dp[i][i] = 0;
dp[i][j]= min( dp[k][j-1]+ cal( i, i-k ));
cal( i, i-k ): 以i结尾长度为i-k的子串成为回文串的最小修改次数。
cal()可以预处理出来,cal(), 和DP都是 O( 500*500*500 )的复杂度,应该可以用dp优化;
同时为了记录+号的位置,pos[i][j]: 表示dp[i][j]取得最优值时,i前面第一个+出现在哪个字符后后面。
E题
给定长度n<= 200000的串,要求最长的满足v<= 2*c 的子串长度及相应的个数。v表示元音字母个数,c表示辅音字母个数;
我的考虑是 如果v[i] <= 2*c[i], 那么用i更新ans,这是肯定的。
如果不满足上式呢? 有 v[i] - v[j] <= 2* ( c[i]- c[j] ): ==> 2*c[j]- v[j] <= 2*c[i] - v[i];
也即我们需要找到比i前面 比 (2*c[i]-v[i]) 小或相等的 j,且取最小的那个,解决方法是以 2*c[i]-v[i] 作为索引,以i作为值建立线段树维护最小值;
又考虑到 v[i] <= 2*c[i], 那么用i更新ans , 建立线段树是针对 v[i] > 2*c[i]的i,且值是负数,可以加上一个add= n+1;,这样总区间是
[ 1,n ],。
当然会有更方便写的数据结构,我一时没有想到。
具体见代码。
A题
给定一个CCPPCCPPCCCCCPPPP这样的只有C,P的串,从左到右,每次最多取5个字符,每次取的字符必须相同,问最少要取多少次。
我的代码比较短:
每次循环定个初始位置,以该位置的下一个位置开始for循环4次.
int main() { int ans,i,n; char ch[110]; while(cin>>ch){ n= strlen(ch); ans=0; int st=0; while(st<n){ for(i=st+1;i<st+5 && i<n;++i){ if( ch[i]!=ch[i-1] ) break; } ans++; st= i; } cout<< ans <<endl; } }
B题
给定一个序列n<= 5000,每个元素大小介于1到n之间,问至少需要改变多少个元素才能使序列中的元素是两两不同即1到n每个数字各出现一次。
超水,统计没有出现的数字的个数。
C题
给定最多100000个区间,保证坐标x,y都是没有重复的。问有多少个区间是被包含了。
水。。。
按x排升序,然后对于每个区间,看前面已经查询过的区间的y的最大值,这个用一个变量保存就可以了。
鄙视,数组开小了,看成了10000,另外,貌似sort直接对pair排序是默认以first作为第一关键字的。
pair<int,int>p[maxn]; ////// without this ,the code also get a Accepted,and the runtime is 90ms; why; /*bool cmp(pair<int,int>x,pair<int,int>y){ return x.first< y.first; }*/ int main() { int n,i; while(cin>>n){ for(i=1;i<=n;++i){ scanf("%d%d",&p[i].first,&p[i].second); } sort( p+1, p+1+n ); int ans=0,maxval= p[1].second; for(i=2;i<=n;++i){ if( p[i].second < maxval ) ans++; else maxval= p[i].second; } cout<< ans <<endl; } }
D题
给定长度为n的字符串,n<=500,然后是k,要求把串划分为 不多于k个段,可以是1,2,3..k段,要求每段是回文串。 同时为了保证是回文串,需要进行必要的修改字符操作,要求输出最小的修改次数,即最后的结果串,段段之间用+号连接,如果多个答案,随意输出一个。
如:
abdcaba 5
answer:
0 a+b+d+c+aba
我的做法是dp,为了方便,我的字符串从1开始到n作为索引,dp[i][j]: [1,i] 划分为 j段的最小修改次数,显然dp[i][i] = 0;
dp[i][j]= min( dp[k][j-1]+ cal( i, i-k ));
cal( i, i-k ): 以i结尾长度为i-k的子串成为回文串的最小修改次数。
cal()可以预处理出来,cal(), 和DP都是 O( 500*500*500 )的复杂度,应该可以用dp优化;
同时为了记录+号的位置,pos[i][j]: 表示dp[i][j]取得最优值时,i前面第一个+出现在哪个字符后后面。
E题
给定长度n<= 200000的串,要求最长的满足v<= 2*c 的子串长度及相应的个数。v表示元音字母个数,c表示辅音字母个数;
我的考虑是 如果v[i] <= 2*c[i], 那么用i更新ans,这是肯定的。
如果不满足上式呢? 有 v[i] - v[j] <= 2* ( c[i]- c[j] ): ==> 2*c[j]- v[j] <= 2*c[i] - v[i];
也即我们需要找到比i前面 比 (2*c[i]-v[i]) 小或相等的 j,且取最小的那个,解决方法是以 2*c[i]-v[i] 作为索引,以i作为值建立线段树维护最小值;
又考虑到 v[i] <= 2*c[i], 那么用i更新ans , 建立线段树是针对 v[i] > 2*c[i]的i,且值是负数,可以加上一个add= n+1;,这样总区间是
[ 1,n ],。
当然会有更方便写的数据结构,我一时没有想到。
具体见代码。
相关文章推荐
- CF_#322(Div.2) D. Three Logos(greedy)
- Cf 104 div.2
- cf#179(div.2)
- Cf 102 Div.2
- Cf 95 Div.2
- cf 156 div.2 D. Mr. Bender and Square
- CF Round #354 Div.2
- 【数论】CF#364 div.2 B.Cells Not Under Attack
- CF 334 div.2-D Moodular Arithmetic
- CF 334 div.2-D/div.1-B/603B Moodular Arithmetic
- CF 192 DIV.2
- CF 335 div.2-C/div.1-A/605A Sorting Railway Cars
- CF 192 DIV.2
- cf 267 div.2 D Fedor and Essay
- [CF#250 Div.2 D]The Child and Zoo(并查集)
- Cf 101 Div.2
- 【CF】Codeforces Round #466 (Div.2)
- 【CF】196 Div.2 D. Book of Evil
- CF 335 div.1-B/div.2-D/605 B Lazy Student
- Cf 105 Div.2