昨天上午感觉效率还是很高的,下午就不太行了,vp了一场cf,c没出来,真的菜。
可能是好久没有打cf了吧,自己思维方面是真的菜,昨天晚上还想打cf的,结果a题直接没思路....
一个小时都没出来,我是真的菜啊。。。
感觉还是好久没做的原因啊,思维完全跟不上,也不在思考题目,都在梦游...
我是菜鸡。
感觉学了挺多的算法了,但是做题的时候还是不会啊....感觉自己思维还是不太行啊。
以后:洛谷题单+cf(1周三场)+多校都得打啊。
合理利用起来时间很关键!!
P3884 [JLOI2009] 二叉树问题
这题感觉还是很有意思的,
但是我没搞懂最短距离是怎么算出来的...深度就是dfs搜即可,设一个vis【】数组记录在搜索过程中每一层出现的次数即可,然后求最大的即可
最短距离的化就是floyd即可了,其实也就是个板子题目
int check(string a,string b){
for(int i=1;i<=min(a.length(),b.length());i++){//枚举重叠部分
int flag=1;
for(int j=0;j<i;j++){
if(b[j]!=a[a.length()-i+j])flag=0;
}
if(flag)return i;
}
return 0;
}
P1019 [NOIP2000 提高组] 单词接龙
这题写的时候就有思路了,但是读题读错了,没看见每个单词最多出现2次,而且匹配也匹配错了,我真的服了...
思路还是很好想的就是dfs+回溯
说下匹配的事,需要贪心,要使得最后答案长度最大,我们需要最小的匹配即可,即只要能匹配上就break即可
匹配函数如下:其实还是很难想的...
int check(string a,string b){
for(int i=1;i<=min(a.length(),b.length());i++){//枚举重叠部分
int flag=1;
for(int j=0;j<i;j++){
if(b[j]!=a[a.length()-i+j])flag=0;
}
if(flag)return i;
}
return 0;
}
我调了快2个小时,烦死...
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int ans=0;
vector<string>a;
int n;
int vis[30];
char ops;
int check(string a,string b){
for(int i=1;i<=min(a.length(),b.length());i++){//枚举重叠部分
int flag=1;
for(int j=0;j<i;j++){
if(b[j]!=a[a.length()-i+j])flag=0;
}
if(flag)return i;
}
return 0;
}
void dfs(string s,int len){
ans=max(ans,len);
for(int i=0;i<n;i++){
if(vis[i]>=2)continue;
int c=check(s,a[i]);
if(c==0)continue;
vis[i]++;
dfs(a[i],len+a[i].length()-c);
vis[i]--;
}
}
int main(){
cin>>n;
string s1;
for(int i=1;i<=n;i++){
cin>>s1;
a.push_back(s1);
}
cin>>ops;
for(int i=0;i<n;i++){
for(int j=0;j<=n;j++)vis[j]=0;
if(a[i][0]==ops){
vis[i]++;
dfs(a[i],a[i].length());
}
}
cout<<ans<<endl;
return 0;
}
昨天还学了Hash算法..
感觉还是比较简单的,就是进制,一般来说,进制采用31,131,1313比较好,能有效减少冲突。
我们用ull数组来存hash值...
为了取余来着...
ull Hash(string s){
ull ans=0;
ull p=131;
for(int i=0;i<=s.length()-1;i++){
ans=ans*p+s[i]-'a'+1;
}
return ans;
}
昨天还vp了一场cf,出了2道题...排名5000多,我是真的菜啊...
感觉还是做到c题的时候,自己不能完全太专注,静下心来认真思考,老毛病了,高中考试就无法完全专注起来。不然也不会来青稞,也不知道应该怎么改变,反正尽量让自己专注起来吧
A:
A还是比较简单的,
主要情况分两类:x为1或者x不为1
x不为1的话,n就可以由n个1组成
如果x为1的话,结果可以由2和3组成,如果n==1的话就无解
B:
B题也是很简单的,但是做的时候自己思路不是很清晰就开始做了;
导致自己改了好久.....
我们发现如果c1-a1和b1-a1同号的话,答案+min(abs(c1-a1),abs(b1-a1));
b2-a2和c2-a2也是同理的
注意ans最初的赋值应该为1
C.
这题就不会了..还是自己的思维跟不上啊
也可能是自己没有专注的想....(主要原因)
其实当时我想的是统计l和r之间每个字符出现的次数,如果次数>s中的数量,就可以,反之就不知道了,但这不是所有情况...
思路:贪心+思维
对于每一位我们希望每一个字符在s中出现的最晚,find(s,k)从第k个位置之后找s
比如l=1,r=3,s=1112222333,我们肯定在把3当作最好的
注意维护位置pos即可
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int t;
string s;
int m;
string s1,s2;
int main(){
cin>>t;
while(t--){
cin>>s>>m>>s1>>s2;
int flag=0;
int pos=0;
int maxn=0;
for(int i=0;i<m;i++){
if(flag)break;
pos=maxn;
for(char j=s1[i];j<=s2[i];j++){
int cnt=s.find(j,pos);
if(cnt>=s.length()){
flag=1;
printf("YES\n");
break;
}
maxn=max(maxn,cnt+1);
}
}
if(flag==0){
printf("NO\n");
}
}
return 0;
}
D:思维+贪心
虽然代码很短,但是还是不太好想
这题k一定等于前i个数的某个和
思路:求最小的子序列,然后前面的前缀和就是k了。
一直不太明白,我当初的思路就是贪心,为什么k不等于最大的子序列呢;
其实正确思路以及包含了这种思路了;而且更优
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int t;
int n;
ll a[300005];
int main(){
cin>>t;
while(t--){
cin>>n;
ll sum=0,minn=0,ans,mc=0,x;
for(int i=1;i<=n;i++){
scanf("%lld",&x);
sum=sum+x;
mc=max(mc,sum);
ll mx=sum-mc;
if(mx<minn){
minn=mx;
ans=mc;
}
}
cout<<ans<<endl;
}
return 0;
}
把握好时间,注重效率!!