这几天过年没怎么写题(说的好像没过年就在写题一样),把最近的比赛补一补吧
这道题我一开始读错了题意,后来看题解,又把把样例仔细看过才搞懂
题意大概就是给两个字符串,然后让我们把第二串去掉中间连续部分,使得剩下的前缀和后缀连起来是第一个串的子串,(这里子串含义类似于LCS,对于第一个串不需要连续,第二个串需要连续。) 并要求中间去掉部分最短,输出剩下的前后缀连起来的子串,如果不存在这个子串输出'-' 。两个串的长度均是1e5。
比如ABCBA ABDEBA ,那么去掉中间连续部分DE,然后得到ABBA,ABBA是ABCBA的子串,且DE是满足条件的最短去掉的部分。
仔细分析一下,大概就是跟双指针有关的。由于这个子串是第二个串的前缀连上后缀(也有可能只是的后缀或者前缀),我们存一下第二个串的前缀每个字符到达第一个串的位置,
比如DABCBAE ABDEBA 得到2 3 -1 -1 -1 -1 (-1的意思就是这个字符匹配不上了,实际上为了方便可以把数组预设为INF,然后大于第一个串长度的都视为匹配不上)
同样的方式我们处理一下后缀部分,然后我们得到了两个数组
比如abacaba abcdcba,得到1 2 4 -1 -1 -1 -1 和 -1 -1 -1 -1 4 6 7
我们现在要做的就是找到一对(i,j),j > i且bj > ai,同时j-i最小。 指针p1初始指向第一个数组的最后一个合法元素(合法元素指这里的字符能匹配的上,不是-1或者INF)指针p2初始指向第二个数组最后一个元素再往后移动一位的位置。
然后p2每次向前移动一位,如果p2<=p1或者b[p2]<=a[p1],p1向前移动一位,然后每次维护一下p2 - p1的min值。注意一下有可能只去掉前缀或者只去掉后缀,边界问题处理一下
cf762A
题意大概是给一个数字n,让我们求这个数字的因子并且从小到大排序后,求第k大的因子,如果不存在在输出-1
n<= 1e15 k<=1e9这个数字看上去很吓人,但是仔细想一下,由于因子是成对出现的,我们只要枚举到sqrt(n)就能知道这个数字有多少因子,然后丢到一个集合里排序后输出即可,而且即使是1e15也没有1e7的因子。所以直接写就可以了。
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<iostream>
using namespace std;
#define LONG long long
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
LONG num[100000];
int main()
{
LONG n , k;
cin>>n>>k;
int tot = 0;
for(LONG i = 1 ; i* i <= n ;++ i)
{
if( i * i == n ) {num[ ++tot ] = i;break ;}
if(n % i == 0)
{
num[++ tot ] = n/i;
num[++ tot ] = i;
}
}
sort( num + 1 , num + tot + 1);
if( k > tot )cout<<-1 <<endl;
else cout<<num[k]<<endl;
}
cf 762B
大概意思就是需要购进一批鼠标,有两种接口,现在实验室有只能插A接口的电脑a台,只能插B接口的电脑b台,两个接口都有的电脑c台,问我们在优先使得购进尽量多且合适的鼠标的前提下,最小的价格是多少
这道题我也不太能证明,就是先把鼠标按价格排序后,优先满足单一接口的电脑,然后剩下的给两个接口的电脑。过程比较简便。
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<iostream>
using namespace std;
#define LONG long long
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
struct Mouse
{
int v ;
char name[50];
}mouse[3500000];
bool cmp( Mouse a , Mouse b)
{
return a.v < b.v;
}
int main()
{
int a , b , c;
scanf("%d%d%d",&a,&b,&c);
int m ;
cin>>m;
for(int i = 1; i <=m ;++i)
scanf("%d",&mouse[i].v),
scanf("%s",mouse[i].name);
sort( mouse +1 , mouse + m +1 , cmp );
int tot = 0 ;
LONG sum_mon = 0;
for(int i =1 ;i <= m ;++ i)
{
if(mouse[i].name[0] == 'U')
{
if(a > 0)
a--;
else if( c > 0)
c -- ;
else continue ;
tot ++ ;
sum_mon += (LONG )mouse[i].v;
}
else
{
if(b > 0)
b-- ;
else if ( c > 0)
c -- ;
else continue ;
tot ++ ;
sum_mon += (LONG)mouse[i].v;
}
}
printf("%d %lld\n",tot , sum_mon);
}
cf 763C (双指针)
这道题我一开始读错了题意,后来看题解,又把把样例仔细看过才搞懂
题意大概就是给两个字符串,然后让我们把第二串去掉中间连续部分,使得剩下的前缀和后缀连起来是第一个串的子串,(这里子串含义类似于LCS,对于第一个串不需要连续,第二个串需要连续。) 并要求中间去掉部分最短,输出剩下的前后缀连起来的子串,如果不存在这个子串输出'-' 。两个串的长度均是1e5。
比如ABCBA ABDEBA ,那么去掉中间连续部分DE,然后得到ABBA,ABBA是ABCBA的子串,且DE是满足条件的最短去掉的部分。
仔细分析一下,大概就是跟双指针有关的。由于这个子串是第二个串的前缀连上后缀(也有可能只是的后缀或者前缀),我们存一下第二个串的前缀每个字符到达第一个串的位置,
比如DABCBAE ABDEBA 得到2 3 -1 -1 -1 -1 (-1的意思就是这个字符匹配不上了,实际上为了方便可以把数组预设为INF,然后大于第一个串长度的都视为匹配不上)
同样的方式我们处理一下后缀部分,然后我们得到了两个数组
比如abacaba abcdcba,得到1 2 4 -1 -1 -1 -1 和 -1 -1 -1 -1 4 6 7
我们现在要做的就是找到一对(i,j),j > i且bj > ai,同时j-i最小。 指针p1初始指向第一个数组的最后一个合法元素(合法元素指这里的字符能匹配的上,不是-1或者INF)指针p2初始指向第二个数组最后一个元素再往后移动一位的位置。
然后p2每次向前移动一位,如果p2<=p1或者b[p2]<=a[p1],p1向前移动一位,然后每次维护一下p2 - p1的min值。注意一下有可能只去掉前缀或者只去掉后缀,边界问题处理一下
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<iostream>
using namespace std;
#define LONG long long
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
int num [30][100100];
char str1[100100];
char str2[100100];
int a[100100];
int b[100100] ;
int main()
{
clr1( a );
clrI( b ) ;
scanf("%s%s",str1 , str2 );
int len1 = strlen(str1);
int len2 = strlen(str2);
int j,i;
j = 0;
for( i = 0 ; i < len2 ;++ i)
{
while(str1[j] != str2[i] && j < len1) ++ j;
if( j >= len1)break ;
a[i] = j ;
j++;
}
int p1 = i - 1;
j = len1 - 1;
for( i = len2 - 1 ; i >= 0 ; -- i)
{
while ( str1[j] != str2[i] && j >= 0) -- j;
if(j < 0 )break ;
b[i] = j;
-- j;
}
int p2;
if(b[len2 - 1] > a[p1]) p2 = len2 - 1;
else p2 = len2 ;
int res = p2 - p1;
for( i = p1 , j = p2 ; ; )
{
if( j < 0 || b[j] == -1&& j < len2)break ;
if(i >= 0)
if(a[i] >= b[j]|| j <= i)
{
-- i;
}
if(res > j - i)
{
res = j - i;
p1 = i , p2 = j;
}
j -- ;
}
if(p1 < 0 && p2 >= len2)cout<<'-'<<endl;
else{
if( p1 == p2 ) p2 ++ ;
for( i = 0 ; i <= p1 ; ++ i)printf("%c",str2[i]);
for( i = p2 ; i <= len2 -1 ; ++ i) printf("%c",str2[i]);}
}