标签:
1001
http://acm.hdu.edu.cn/showproblem.php?pid=5054
输出Yes只有一种情况.
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#define rd(x) scanf("%d",&x)
#define rd2(x,y) scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
int dx[8]={0,0,-1,1,1,1,-1,-1};
int dy[8]={1,-1,0,0,-1,1,-1,1};
//关键点是中点吧
int n,m,x,y;
int main()
{
while(cin>>n>>m>>x>>y)
{
if(2*x==n&&2*y==m)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
1002
http://acm.hdu.edu.cn/showproblem.php?pid=5055
给出n个数字(每个数字0~9),用这n个数字组成一个数,要求不能有前导0,且最后一位必须是奇数。不能组成则输出-1.
可以构造出数的情况有: 只有一个数,且该数是奇数;n个数中大于0的数至少有2个,且n个数中存在奇数。
如果能满足的话,那么最小的奇数做数的最后一位,剩下的数从大到小排在前面就是所求的数。
写的时候逻辑有点乱.....这类题写的时候一定得考虑全面一些。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#define rd(x) scanf("%d",&x)
#define rd2(x,y) scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
int dx[8]={0,0,-1,1,1,1,-1,-1};
int dy[8]={1,-1,0,0,-1,1,-1,1};
const int maxn=102;
int num[maxn];
bool hasodd;
int minodd;
int n;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
while(rd(n)!=EOF)
{
hasodd=0;
minodd=100;//最小的奇数
int p=-1;//最小的奇数的位置
int cnt=0;//大于0的数字有多少个
for(int i=1;i<=n;i++)
{
rd(num[i]);
if(num[i]>0)
cnt++;
if(num[i]&1)
{
hasodd=1;
if(minodd>num[i])
{
minodd=num[i];
p=i;
}
}
}
if(n==1)
{ if(hasodd)
cout<<num[1]<<endl;
else
cout<<-1<<endl;
continue;
}
if(cnt>=2&&hasodd)
{
swap(num[p],num[n]);
sort(num+1,num+n,cmp);
for(int i=1;i<=n;i++)
cout<<num[i];
cout<<endl;
}
else
cout<<-1<<endl;
}
return 0;
}
1003
http://acm.hdu.edu.cn/showproblem.php?pid=5056
给出一个只有小写字母组成的字符串,然后给出一个数字k,问有多少子串满足 该子串中相同字母出现的次数不超过k。比如有一个子串 abac k=2的话,a的次数=2不超过k,b,c的次数均为1,也不超过k,所以这个子串就是符合要求的.
一个长度为n的字符串,子串一共有n(n+1)/2个,题目中n是100000,直接枚举肯定不行。
一开始想的也是枚举,枚举每个位置,判断以该位置开头的子串有多少个,两重循环,第二重循环就是长度了,一开始以为长度最多就是26(26个字母),复杂度还可以,但是忘了k的事...k不一定等于1啊,有可能很大....所以悲剧了,果断超时..
看到解题报告是 也是枚举每个位置,统计的则是以该位置为结尾的最大子串的长度,则是以该位置结尾的所有子串的个数,这个好理解,比如k=2, bcca,当位置为a时,满足条件的最大子串为 bcca,长度为4,那么满足的所有子串的个数也为4,分别为 bcca cca ca a。开辟两个指针,一个是枚举的位置,一个是满足该位置的最大串的起始位置,处治为该串的第一个位置。map<char,int>mp,记录每个字母出现的次数.下面以具体例子来说明是怎么工作的吧,解释不清楚.....
比如串 abbcbcc k=2
一开始位置为1, ‘a‘,起始指针start为1,mp[‘a‘]++, 该值满足<=k,ans+= i-start+1 ;即ans+=1,对应的串为a
后来位置为2,‘b‘, 起始指针start为1, mp[‘b‘]++, 满足条件, ans+= 2-start+1; 即ans+=2,对应的串为 b ab
后来位置为3,也满足条件,ans+=3,对应的串为 b bb abb
后来位置为4, 也满足条件,ans+=4;对应的串为 c bc bbc abbc
后来位置为5, mp[‘b‘]++,这时候mp[b]=3, 3>k,不符合条件,原因是b这个字母多了一个,要想以该位置为结尾,那么就得从前面去掉一个b,要求最大串,所以去掉最前面的一个b,同时更新起始位置, 这时候起始位置还是1,要想符合条件,就得移动该指针,mp[‘a‘]--,这是起始指针start对应的位置,start++, 这时候start=2,对应的字母为b,找到第一个b了,要把它去掉,所以再执行一次 mp[‘b‘]--,start++, 这时候start=3, 符合题意了, 满足的最大串为 bcb, ans+= 5-start+1,即ans+=3 ,对应的子串为 b cb bcb
后来同理....
从上面流程中可以看出start指针是一直往前的,这个效率比前面说的那个要高,有些位置满足的子串数可以0(1)来计算出
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#define rd(x) scanf("%d",&x)
#define rd2(x,y) scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
int dx[8]={0,0,-1,1,1,1,-1,-1};
int dy[8]={1,-1,0,0,-1,1,-1,1};
char s[100004];
map<char,int>mp;
int len;
int k;
ll ans;
int main()
{
int t;rd(t);
while(t--)
{
mp.clear();
scanf("%s",s+1);
rd(k);
len=strlen(s+1);
int start=1;
ans=0;
for(int i=1;i<=len;i++)
{
mp[s[i]]++;
if(mp[s[i]]>k)
{
while(s[start]!=s[i])
{
mp[s[start]]--;
start++;
}
mp[s[start]]--;
start++;
}
ans+=i-start+1;
}
printf("%I64d\n",ans);
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/sr_19930829/article/details/43638667