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的方式方法,代码还需再研究研究。