E
给n个点,每个点的关联点位置为i-a[i],i+a[i];要检查位置是否在范围内,关联一次花费为1,找出每个点关联到与他的值的奇偶性相反的点的最小花费。
最初思路:第一感觉是dfs,但是要找最小花费,也就是最小路径,仔细观察发现,每个点的关联点是固定的,并且存在无法被关联的点,而且要想奇偶性相反,一定需要通过一个变点,就是改变奇偶性的点,并且一个点要想达成目标,只需要在找的过程中通过一个变点就够了,那么如果能通过一种结构或者说是预处理,能使找的时候从变点开始倒着找出所有被关联的点记录下来,而不被关联的点就是不行的点,那么问题就差不多解决了,感觉上和并查集的特点挺像,但是半天写不出来,好像不行,哎!
A
给三个坐标,每个都能至多左移一位或右移一位或不移动,问操作后三个坐标两两差的绝对值最小是多少。
思路:先算初始值,操作后能拉近的最大距离为4
C
给一串字符串,在给出能用于打印的字母,定义连续的一串字符为其子串,问能打印出多少种原字符串的子串。
思路 :类似桶排序,然后套公式。
D
给n个数,能够删除一个数或不删,找最长的连续上升子串,子串定义为原来串的连续元素。
思路:预处理出不删时候的各个符合条件的子串长度,然后在子串与子串之间分类讨论链接点。
B
给出一张二维坐标纸,从零零点出发回到零零点,给出上下左右操作,规定不能走重复的格点,可以对给出的操作任意删除和排序,求满足条件的最小删除量。
思路:上几个下几个,左几个右几个,找小值。
F
给两个仅仅由左右括号组成的字符串,长度分别为s,t;
找出最短的匹配的括号序列,使得这个序列的子串既能表示出第一个给定的序列,又能表示出第二个给定的序列。这里子串可以不为连续元素。
初始思路:新序列的左括号数大于等于前两者的最大值,右括号数大于等于前两者的最大值。找出左右的最大值,然后再考虑匹配与表示子串的问题。然后,额!。。。。。。。。头痛。关键是怎样排列使得子串可以表示出给定串。
A
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int abss(int t)
{
if(t>=0) return t;
else return -t;
}
int main()
{
int q;
scanf("%d",&q);
int ans;
int a,b,c;
while(q--)
{
scanf("%d%d%d",&a,&b,&c);
ans=abss(a-b)+abss(a-c)+abss(b-c);
if(ans>=4) printf("%d\n",ans-4);
else printf("0\n");
}
return 0;
}
B
#include <iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
char s[200005];
int main()
{
int q;
scanf("%d",&q);
int len;
int u,d,l,r;
while(q--)
{
u=0,l=0,r=0,d=0;
scanf("%s",s+1);
len=strlen(s+1);
for(int i=1;i<=len;i++)
{
if(s[i]=='U') u++;
else if(s[i]=='D') d++;
else if(s[i]=='L') l++;
else if(s[i]=='R') r++;
}
int t1=min(u,d);
int t2=min(l,r);
if(t1==0)
{
if(t2!=0)
{
printf("2\nLR\n");
}
else
{
printf("0\n");
}
}
else if(t2==0)
{
if(t1!=0)
{
printf("2\nUD\n");
}
else
{
printf("0\n");
}
}
else
{
printf("%d\n",(t1+t2)*2);
for(int i=1;i<=t1;i++)
{
printf("U");
}
for(int i=1;i<=t2;i++)
{
printf("L");
}
for(int i=1;i<=t1;i++)
printf("D");
for(int i=1;i<=t2;i++)
printf("R");
printf("\n");
}
}
return 0;
}
C
getchar()不要丢。
#include <iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
char s[200005];
int main()
{
int n,k;
int a[26]={0};
scanf("%d%d",&n,&k);
scanf("%s",s+1);
//printf("%s",s+1);
char r;
char ch;
getchar();
for(r=' ';r==' ';scanf("%c",&r))
{
scanf("%c",&ch);
a[ch-'a']=1;
//cout<<"1"<<endl;
}
ll t=0;
ll ans=0;
for(int i=1;i<=n;i++)
{
if(a[s[i]-'a']==1) t++;
else
{
ans=ans+t*(t+1)/2;
t=0;
}
}
if(a[s[n]-'a']==1)
{
ans=ans+t*(t+1)/2;
}
printf("%lld\n",ans);
return 0;
}
D
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[200005];
int l[200005];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int i=1;
int cnt=1;
l[1]=1;
while(i<=n)
{
i++;
if(a[i]>a[i-1])
{
l[cnt]++;
}
else
{
cnt++;
l[cnt]=1;
}
}
/*for(int i=1;i<=cnt;i++)
cout<<l[i]<<endl;
cout<<endl;*/
int tt=0;
int ans=0;
for(int i=1;i<=cnt;i++)
{
int b=tt+l[i];
if(a[b]<a[b+2])
{
if(a[b+1]<a[b+2])
{
ans=max(l[i]+l[i+1]-1,ans);
tt=b;
}
else
{
ans=max(l[i]+l[i+2],ans);
tt=b;
}
}
else if(b-1!=0&&a[b-1]<a[b+1])
{
ans=max(ans,l[i]+l[i+1]-1);
tt=b;
}
else
{
ans=max(l[i],ans);
tt=b;
}
}
printf("%d\n",ans);
return 0;
}
E
并查集不行,但是邻接表倒着建立,结合bfs,然后由奇数点倒着引出所有的偶数点,再由偶数点倒着引出所有的奇数点,也就是由一个变点后,后续的点的奇偶性都是一样的。
由于奇数引偶数,所以最后的时候要亦或1,倒换过来。
网上一个大神的代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 200001, maxm = maxn << 1;
int n, i, s, a[maxn], f[maxn][2];
int to[maxm], nxt[maxm], head[maxn];
queue<int>q;
inline int read()
{
int x = 0;
char ch = getchar();
while (ch < '0' || ch>'9') ch = getchar();
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
return x;
}
void add(int x, int y)
{
to[++s] = y;
nxt[s] = head[x];
head[x] = s;
}
void bfs(int x)
{
for (i = 1; i <= n; i++)
if ((a[i] & 1) == x)
{
f[i][x] = 0;
q.push(i);
}
else f[i][x] = -1;
int k;
while (q.empty() == 0)
{
k = q.front();
q.pop();
for(int i=head[k];i;i=nxt[i])
if (f[to[i]][x] == -1)
{
f[to[i]][x] = f[k][x] + 1;
q.push(to[i]);
}
}
}
int main()
{
n = read();
for (i = 1; i <= n; i++) a[i] = read();
//s = 0;
for (i = 1; i <= n; i++)
{
if (i - a[i] > 0) add(i - a[i], i);
if (i + a[i] <= n) add(i + a[i], i);
}
bfs(0);
bfs(1);
for (i = 1; i <= n; i++) printf("%d ", f[i][(a[i] & 1) ^ 1]);
return 0;
}
F
大概了解了一下 搜索+dp的方式方法,代码还需再研究研究。