你在玩俄罗斯方块,给出一个数组a,a[i]表示第i堆俄罗斯方块的个数,你可以用n个2*1的小长条去填补它(高为2,宽为1),规则同我们平时玩的俄罗斯方块,一列满了就可以消了。问你这堆有没有可能全部消掉。
思维题,通过不断尝试易知只要该数组所有数的奇偶性相同就有可能消掉。
当时本着位运算快一点的想法,判断奇偶性用的 x&1 后面发现老是不行,原来要(x&1),括号包起来下。
#include
#define mem(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inf=0x7f7f7f7f;
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
ll T,x,n,t;
bool flag;
int main()
{
read(T);
while(T--)
{
t=0;
read(n);
cin>>x;
t=x%2;
flag=false;
for(int i=1;i<n;i++)
{
read(x);
if(x%2!=t)
{
flag=true;
}
}
if(flag&&n!=1)
{
puts("NO");
}
else
{
puts("YES");
}
}
return 0;
}
给你一个字符串,问他的子串(不一定连续)有没有至少一个长度不少于3的回文串
用一个数组记录数a[i]出现的第一个位置,然后如果再遇到它并且两者之间至少有一个数,就可以构成
#include
#define mem(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inf=0x7f7f7f7f;
const int maxn=5000+100;
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
ll T,n,x,vis[maxn];
bool flag;
int main()
{
read(T);
while(T--)
{
flag=true;
memset(vis,-1,sizeof(vis));
read(n);
for(int i=0;i<n;i++)
{
read(x);
if(!flag)
{
continue;
}
if(vis[x]>=0&&i-vis[x]>1)
{
puts("YES");
flag=false;
}
else if(vis[x]<0)
{
vis[x]=i;
}
}
if(flag)
{
puts("NO");
}
}
return 0;
}
有一只小青蛙,他开始时在0号位置,他要到n+1号位置去,中间1-n位置用一个字符串描述他的行动规则。如果s[i]是L,则他必须向左走,且在不超出范围的情况下至少走一步,它也可以走d步,同理R则是向右走。问在这只小青蛙能够到达n+1号位置的情况下,d的最小值是多少
这个很像二分答案,然而二分答案不好做,可能会TLE,正解应该是寻找最近的R值之间的距离。可以这样理解,如果小青蛙跳在了L上,他想走出去总要跳到一个R上面去,如果用贪心的思想,那就让他每次都是走在R上面。而这种情况下,最小的d应该就是两个R之间的最小距离。这里将n+1号位置标为R,可以更好处理n+1号点,读者可以自己动手试试。
#include
#define mem(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inf=0x7f7f7f7f;
const int maxn=2e5+10;
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
ll T;
ll ans,n,before;
char s[maxn];
int main()
{
read(T);
while(T--)
{
before=0;
ans=0;
s[0]='L';
scanf("%s",s+1);
n=strlen(s);
s[n]='R';
for(int i=1;i<=n;i++)
{
if(s[i]=='R')
{
ans=max(ans,i-before);
before=i;
}
}
write(ans);
putchar('\n');
}
return 0;
}
给出两个数组a和b,求满足a[i]+a[j]>b[i]+b[j]的(i,j)对有多少个。其中(i,j),(j,i)算一对。
比较操蛋的题,开始还以为这里的i和j是有先后顺序的,后来才发现他们是无序的。计算c[i]=a[i]-b[i],然后对c[i]进行排序,如果满足上述条件的话,应该有c[i]+c[j]=a[i]-b[i]+a[j]-b[j]>0。用两个指针l和r计算配对数即可。
#include
using namespace std;
typedef long long ll;
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
const ll maxn=2e5+10;
ll n,a[maxn],b[maxn],c[maxn],l,r,ans;
int main()
{
read(n);
for(int i=1;i<=n;i++)
{
read(a[i]);
}
for(int i=1;i<=n;i++)
{
read(b[i]);
}
for(int i=1;i<=n;i++)
{
c[i]=a[i]-b[i];
}
sort(c+1,c+1+n);
l=1,r=n,ans=0;
while(l!=r)
{
if(c[l]+c[r]>0)
{
ans+=r-l;
r--;
}
else
{
l++;
}
}
write(ans);
return 0;
}
Vova有一个奇怪的睡眠习惯,Vova会睡上刚好N次。第i次他会在他上一次醒来的a[i]个小时后睡觉。你可以假设Vova是在开头醒来的(初始时间是第0小时)。每次Vova刚好睡一天(换言之,h小时,这个h小时不是平时的24小时,题中会给出)。当他的第i次睡眠在l点和r点之间进行时被称之为好睡眠。它可以控制自己在第i次睡眠预定的a[i]小时后睡觉,也可以是在a[i]-1小时后。求这n次睡眠他的好睡眠最多可以有多少次
去看看题目后面的note能更好理解题意。本题用DP,状态转移方程在代码里。
#include
#define mem(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inf=0x7f7f7f7f;
const int maxn=2000+200;
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
ll n,h,l,r,x,ans=0;
ll sum[maxn],dp[maxn][maxn];
void init()
{
mem(sum);
mem(dp);
read(n);
read(h);
read(l);
read(r);
for(int i=1;i<=n;i++)
{
read(x);
sum[i]=x+sum[i-1];
}
return;
}
void work()
{
for(int i=1;i<=n;i++)
{
for(int j=0;j<=i;j++)
{
dp[i][j]=max(dp[i-1][j],j ? dp[i-1][j-1]:0)+bool((sum[i]-j)%h>=l&&(sum[i]-j)%h<=r);
}
}
for(int i=0;i<=n;i++)
{
ans=max(ans,dp[n][i]);
}
write(ans);
return;
}
int main()
{
init();
work();
return 0;
}
给定一棵树,每个节点还有额外的属性颜色。每个数的W值等于白点数-黑点数,求包含i节点的树的最大 w值
比赛的时候没看到这题,看到大佬们的代码时还以为又是link-cut-tree等我不知道的玄学算法,后面仔细看了看并不是。树形DP,第一次dfs尽量的找到附近的能使子树W值最大的节点(但访问不到转过来的father父节点),后面的dfs2便是处理father那边的节点,尽量弄大
#include
#define mem(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inf=0x7f7f7f7f;
const int maxn=2e5+10;
vector<int> e[maxn];
int ans[maxn],a[maxn];
int n,u,v;
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
int dfs(int u,int fa)
{
ans[u]=a[u] ? 1:-1;
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i];
if(v!=fa)
{
ans[u]+=max(0,dfs(v,u));
}
}
return max(0,ans[u]);
}
void dfs2(int u,int fa)
{
if(ans[u]==-1)
{
ans[u]+=max(0,ans[fa]);
}
else
{
ans[u]=max(ans[u],ans[fa]);
}
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i];
if(v!=fa)
{
dfs2(v,u);
}
}
return;
}
int main()
{
read(n);
for(int i=1;i<=n;i++)
{
read(a[i]);
}
for(int i=1;i<n;i++)
{
read(u);
read(v);
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,1);
dfs2(1,0);
for(int i=1;i<=n;i++)
{
write(ans[i]);
putchar(' ');
}
return 0;
}