Jeanny
寂兮,寥兮,独立不改,周行而不殆

考点:

题目描述

给定长度非零的非空 01 串 S。

找出 S 的非空连续子串 T 满足串中 0 的个数减去 1 的个数最大。

你只需要输出最大值即可。

// 1 -1 -1 -1 -1 -1 1 1 -1 1 -1
// 前缀和
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
string s;
int a[100005], mn, ans, sum[100005];
int main(){
    cin>>s;
    int n = s.length();
    a[0] = sum[0] = mn = ans = (s[0] - '0' == 0 ? 1 : -1);
    mn = min(ans, 0);
    for(int i = 1; i < n; i++){
        a[i] = s[i] - '0';
        a[i] = (a[i] == 0 ?  1 : -1);
        sum[i] = sum[i-1] + a[i];
        ans = max(ans, sum[i] - mn);
        mn = min(mn, sum[i]);
    }
    cout<<ans<<endl;
    return 0;
}
/*
111111
0 1  0 0 0  0  1  1  0
1 -1 1 1 1  1 -1  -1 1
1 0  1 2 3  4

0 0
1 1
*/

T2 P1944 最长括号匹配  栈/dp

// 第一种思路:
// ( [ (  ] [ ( )  ]  ]  ( )
// 1 2 1 -2 2 1 -1 -2 -2 -1 1
// 1 3 4  2 4 5 4  4  2  1  2
// 改进?改变?
// )   )( )(   (   )  ) (  )  )
// -1 -1  1  1   1  -1  -1  1  -1 -1
// -1 -2  1  2   3  2   1   2  1
// 弹出来
//
// (())((()
//
// if(top() == "(") q.pop();
//
// ( [ (  ] [ ( ) ] [] [ () ( () ]
//  (  [  (  )  ]
    // 1  2  3  4
// ( [ ( ]
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
string s;
stack<int> q;
int f[10000005], ans;
int main(){
    // freopen("bracket.in","r",stdin);
    // freopen("bracket.out","w",stdout);
    memset(f, 0x7f, sizeof f);
    cin>>s;
    int len = s.length();
    for(int i = 0; i < len; i++){
        if(s[i] == '(' || s[i] == '['){
            q.push(i);
            // cout<<"yyy1: "<<s[i]<<endl;
        }
        /*
        (  [  (  ]  [  (  )  ]  [  ]  (   )
        0  1  2  3  4  5  6  7  8  9  10 11
        ([(][()][]()
        */
        else if(s[i] == ')'){
            if(!q.size()){
                 q.push(i);
                 // cout<<"yyy2: "<<s[i]<<endl;
            }
            else if(s[q.top()] == '('){
                q.pop();
                if(!q.size()) f[i] = -1;
                else f[i] = q.top();
                // cout<<"hhh: "<<i<<" "<<f[i]<<endl;
            }
            else{
                q.push(i);
                // cout<<"yyy3: "<<s[i]<<endl;
            }
        }
        else if(s[i] == ']'){
            if(!q.size()){
                 q.push(i);
                 // cout<<"yyy4: "<<s[i]<<endl;
            }
            if(s[q.top()] == '['){
                q.pop();
                if(!q.size()) f[i] = -1;
                else f[i] = q.top();
                // cout<<"ppp: "<<i<<" "<<f[i]<<endl;
            }
            else {
                q.push(i);
                // cout<<"yyy5: "<<s[i]<<endl;
            }
        }
    }
    // cout<<"ooo: "<<f[7]<<endl;
    int bg = 0, ed = 0, mxlen = 0;
    for(int i = 0; i <= len; i++){
        // cout<<"www:"<<i<<" "<<f[i]<<endl;
        if(i - f[i] > mxlen){
            bg = f[i] + 1, ed = i;
            // cout<<"bbb: "<<bg<<" "<<ed<<endl;
            mxlen = i - f[i];
        }
    }
    if(mxlen == 0){
        return 0;
    }
    for(int i = bg; i <= ed; i++) cout<<s[i];
    // cout<<endl;
    return 0;
}
/*


()[]

((()))[][[]][][]([][][][]]]][]][
((()))[][[]][][]
*/


DP的写法
/*
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;

const int L=1000005;
char s[L];
int l,f[L],Ans,id;

int main()
{
	scanf("%s",s+1);//输入,下标从1开始
	l=strlen(s+1);//下标从1开始的字符串长度
	for(int i=2;i<=l;++i)//s[1]显然无法匹配,所以从2开始
		if(s[i]=='('||s[i]=='[') continue;//如分析
		else
			if((s[i]==')'&&s[i-f[i-1]-1]=='(')
			||(s[i]==']'&&s[i-f[i-1]-1]=='['))
			{
				f[i]=f[i-1]+2+f[i-f[i-1]-2];
				if(f[i]>Ans) Ans=f[i],id=i;//Ans记录最长括号匹配,id记录最长括号匹配的下标
			}
	for(int i=id-Ans+1;i<=id;++i) printf("%c",s[i]);
	putchar('\n');
	return 0;
}

*/

在数轴上有 N 头牛,第 iii 头牛位于 xi (0≤xi≤109)x_i\:(0\le x_i\le 10^9)xi(0xi109) 。没有两头牛位于同一位置。
有两种牛:白牛和花斑牛。保证至少有一头白牛。你可以把白牛涂成花斑牛,不限数量,不限哪只。
找一段尽量长的区间,使得区间的两端点均有一头牛,且区间中白牛与花斑牛的数量相等。试求区间长度。


分析:尺取法是错的额
#include<bits/stdc++.h>
using namespace std;
int x, n, s, ans, vis[100005];
char c;
struct Node{
    int p,v;
    bool operator <(const Node &A)const{
        return p < A.p;
    }
}a[100005];
int main(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i++){
        scanf(" %d %c",&a[i].p, &c); 
         a[i].v = (c == 'W'? 1: -1);
    }
    sort(a+1, a+n+1);
    for(int i = 1; i <= n; i++){
        s += a[i].v;
        if(s >= 0){
            if(s % 2 == 0)
                ans = max(ans, a[i].p - a[1].p);
            else
                ans = max(ans, a[i].p - a[2].p); 
        }
        else{
            if(!vis[-s]) vis[-s] = a[i+1].p;
            else ans = max(ans, a[i].p - vis[-s]);
        }
    }
    printf("%d\n", ans);
    return 0;
}

一开始尺取法:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n, sm[100005];
struct Node{
    int p; char c;
}a[100005];
bool cmp(Node x, Node y){
    return x.p < y.p;
}
int main(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i++)
        scanf("%d %c",&a[i].p, &a[i].c);
    sort(a+1, a+n+1, cmp);
    for(int i = 1; i <= n; i++){
        if(a[i].c == 'W')
            sm[i] = sm[i-1] + 1;
        else
            sm[i] = sm[i-1] - 1;
    }

    int i = 1, j = n;
    while(i < j){
        if((sm[j] - sm[i-1]) >= 0 && (sm[j] - sm[i-1]) % 2 == 0){
            printf("%d\n", a[j].p - a[i].p);
            return 0;
        }
        else{
            int mx1 = 0, mx2 = 0;
            if((sm[j] - sm[i]) >= 0 && (sm[j] - sm[i]) % 2 == 0){
                mx1 = a[j].p - a[i+1].p;
            }
            if((sm[j-1] - sm[i-1])>= 0 &&(sm[j-1] - sm[i-1]) % 2 == 0){
                mx2 = a[j-1].p - a[i].p;
            }
            if(mx1 == 0 && mx2 == 0){
                i++, j--;
            }
            else if(mx1 >= mx2){
                printf("%d\n", mx1);
                return 0;
            }
            else{
                printf("%d\n", mx2);
                return 0;
            }

        }
    }
    printf("0\n");
    return 0;
}
//100000  尺取法?

//     W    S       W     W   S
// 1 2 3 4  5  6 7  8  9  10  11
//     1    -1      1     1   -1
//     1    0       1     2   1
// W - s 偶数 0 2 4

//考虑不可能的情况

 

T4 P2908 [USACO08OPEN]Word Power S  小技巧

约翰想要计算他那N(l < =N <= 1000)只奶牛的名字的能量.每只奶牛的名字由不超过1000个字 符构成,没有一个名字是空字体串.

约翰有一张“能量字符串表”,上面有M(1 < =M < =100)个代表能量的字符串.每个字符串 由不超过30个字体构成,同样不存在空字符串.一个奶牛的名字蕴含多少个能量字符串,这个名 字就有多少能量.所谓“蕴含”,是指某个能量字符串的所有字符都在名字串中按顺序出现(不 一定一个紧接着一个).

所有的大写字母和小写字母都是等价的.比如,在贝茜的名字“Bessie”里,蕴含有“Be” “si” “EE”以及“Es”等等字符串,但不蕴含“Ls”或“eB” .请帮约翰计算他的奶牛的名字 的能量.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
string a[1005], c[1005];
int n, m, b[150];
bool chk(string x, string y){
    int j = 0;
    for(int i = 0; i < x.length(); i++)
        if(y[j] == x[i]){
            // cout<<"yy: "<<y[j]<<endl;
            j++;
        }
    // cout<<"YYY"<<j<<" "<<y.length()<<endl;
    if(j == y.length()) return 1;
    else return 0;
}
int main(){
    cin>>n>>m;
    for(int i = 0; i < n; i++){
        cin>>a[i]; int len = a[i].length();
        for(int j = 0; j < len; j++) a[i][j] = tolower(a[i][j]);
    }
    for(int i = 0; i < m; i++){
        cin>>c[i]; int len = c[i].length();
        for(int j = 0; j < len; j++) c[i][j] = tolower(c[i][j]);
    }

    for(int i = 0; i < n; i++){
        int cnt = 0;
        for(int j = 0; j < m; j++){
            if(chk(a[i], c[j])){
                cnt++;
                // cout<<"ppp: "<<a[i]<<" "<<c[j]<<endl;
            }
        }
        cout<<cnt<<endl;
    }

    return 0;
}
/*
5 3
Angola
Bessie
Jonathan
Montgomery
Alicia
se
nGo
Ont

abcdefg
aaa
*/

T5 P5833 [USACO19DEC]Livestock Lineup B  全排列

每天,Farmer John 都要给他的 8头奶牛挤奶。她们的名字分别是 Bessie,Buttercup,Belinda,Beatrice,Bella,Blue,Betsy,和 Sue。

不幸的是,这些奶牛相当难以伺候,她们要求 Farmer John 以一种符合 NNN 条限制的顺序给她们挤奶。每条限制的形式为“X 必须紧邻着 Y 挤奶”,要求奶牛 X在挤奶顺序中必须紧接在奶牛 Y 之后,或者紧接在奶牛 YYY 之前。

请帮助 Farmer John 求出一种满足所有限制的奶牛挤奶顺序。保证这样的顺序是存在的。如果有多种顺序都满足要求,请输出字典序最小的一种。也就是说,第一头奶牛需要是所有可能排在任意合法奶牛顺序的第一位的奶牛中名字字典序最小的。在所有合法的以这头字典序最小的奶牛为首的奶牛顺序中,第二头奶牛需要是字典序最小的,以此类推。

输入:

3
Buttercup must be milked beside Bella
Blue must be milked beside Bella
Sue must be milked beside Beatrice

输出:

Beatrice
Sue
Belinda
Bessie
Betsy
Blue
Bella
Buttercup
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
int n;
string c[10], a[10]={"","Beatrice","Belinda","Bella","Bessie","Betsy","Blue","Buttercup","Sue"};//赋初值
string t[10][10];
map<string, int> vis;
int find(string t){
	for(int i=1;i<=8;i++)
		if(c[i]==t) return i;
	return 0;
}
bool judge(){
	for(int i=1;i<=n;i++){
		if(abs(find(t[i][1])-find(t[i][6])) != 1)//相邻
			return false;
	}
	return true;
}
void dfs(int t){
	if(t == 9){
		if(judge()){
			for(int j=1;j<=8;j++) cout<<c[j]<<endl;
			exit(0);
		}
		return;
	}
	for(int i = 1; i <= 8; i++){
		if(!vis[a[i]]){
			vis[a[i]] = 1;
			c[t] = a[i];
			dfs(t+1);
			c[t] = "";
			vis[a[i]] = 0;
		}
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=6;j++)
			cin>>t[i][j];
	}
	dfs(1);
	return 0;
}

 

排数字group

http://192.168.15.53:5283/problem/196

 

题目描述

小武有n个数字,这天小武想将数字理的顺一点,小武要把数字分组,每组的个数都是m,并且这m个 数字连续,小武想知道可以做到吗?

输入格式

第一行一个整数t表示数据组数 对于每组数据, 第一行两个整数n,m 第二行N个非负整数,表示数字

输出格式

如果可以做到输出“true”,否则输出“false”

样例

输入

复制3
9 3
1 2 3 6 2 3 4 7 8
6 3
1 2 3 4 6 7
6 3
1 2 3 4 5 6

输出

复制true
false
true

数据范围与提示

对于30%的数据,n<=100,数字<=1000 对于50%的数据,n<=1000 对于100%的数据,1<=m<=n<=10000, 0<=数字<=10^9,t<=10

样例解释

第一组:分成123,234,678 第二组:不行 第三组:分成123,456

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
int n,k,t,x,w;
bool flag=0,ok;
long long d[11000],v[11000];
int main() {
    scanf("%d",&t);
    while(t--) {
        memset(v,0,sizeof(v));
        scanf("%d%d",&n,&k);
        for(int i=1; i<=n; i++)
            scanf("%lld",&d[i]);
        if(k==1)
        {
            printf("true\n");
            continue;
        }
        sort(d+1,d+n+1);
        flag=0;
        for(int i=1; i<=n; i++) {
            x=i,w=0,ok=0;
            if(!v[x])
            {
                v[x]=1;
                for(int j=i+1; j<=n; j++) 
                {
                    if(!v[j]&&d[j]-d[x]==1) 
                    {
                        w++;
                        v[j]=1;
                        x=j;
                        if(w==k-1)
                        {
                            ok=1;
                            break;
                        }
                    }
                }
                if(!ok)
                {
                    flag=1;
                    printf("false\n");
                    break;
                }
            }
        }
        if(!flag)printf("true\n");        
    }
}

 

 



屯一波题目:

 循环数: dfs//  https://www.luogu.com.cn/problem/P1467

P1016 [NOIP1999 提高组] 旅行家的预算 递推 ? https://www.luogu.com.cn/problem/P1016

posted on 2022-09-09 12:15  Jeanny  阅读(201)  评论(0)    收藏  举报