A题: Count Substrings
水题一枚,只需知道有多少个1就行了,假设有x个1,最后答案就是从x个1中选2个1的组合数加上x,因为定义了
s[i]到s[i]也算一个序列。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define sf scanf
#define pf printf
using namespace std;
const int N=5+1e5;
char s[N];
int main()
{
int T;
int i,n;
sf("%d",&T);
while(T--)
{
sf("%d",&n);
sf("%s",s);
long long cnt=0;
for(i=0;i<n;i++)
if(s[i]=='1')
cnt++;
pf("%lld\n",cnt+cnt*(cnt-1)/2);
}
return 0;
}
B题: Reach The Point
题目意思要理解清楚,人只能左或右转再走一步,所以在坐标纸上分析的时候只能走折线,另外要区别坐标是在
y=x直线的上方还是下方,总之自己在坐标纸上模拟一下怎么走(4,2)和(2,4)点,你就会找出规律了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define sf scanf
#define pf printf
using namespace std;
typedef long long LL;
LL SB(LL n){
return n>0?n:(-n);
}
int main()
{
int T;
long long x,y,N,M;
long long ans=0;
sf("%d",&T);
while(T--)
{
sf("%lld%lld",&x,&y);
x=SB(x),y=SB(y);
M=min(x,y),N=max(x,y);
ans=2*M;
if(x>=y)
ans+=(N-M)%2==0?(N-M)/2*4:(3+(N-M)/2*4);
else ans+=(N-M)%2==0?(N-M)/2*4:(1+(N-M)/2*4);
pf("%lld\n",ans);
}
return 0;
}
C题: Chef and Frogs
好题,值得一做,普通方法肯定会TLE,所以用了一种比较奇葩的树状数组,也不枉学了几天的数据结构吧。
大致思路就是先排一遍序,记录下每个数初始的位置在排序后是那个位置,储存在loc数组中,在询问的时候,
把位置a,b转换为在排序后的数组中的位置,这样就可以直接对排序后的数组进行查询了,具体查询就是用比较快的
树状数组实现的,那么具体怎么跟树状数组扯上的呢?对于每个位置,若它与前一个位置的差小于等于K,就更新为1,否则该位置还是保持为0,所以这样一直更新下来,对于每一个询问(a,b),看区间内的数是否全为1,即
read(b)-read(a-1)==b-a+1?等于则是yes,否则还要判断一下,具体见代码:
希望有人交流一下更好的做法。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define sf scanf
#define pf printf
using namespace std;
const int N=5+1e5;
typedef struct node
{
int id,val;
}node;
node po[N];
bool bk[N];
int n,loc[N],tree[N];
int read(int pos){
int ans=0;
while(pos>0)
{
ans+=tree[pos];
pos-=pos&-pos;
}
return ans;
}
void update(int pos,int val){
while(pos<=n)
{
tree[pos]+=val;
pos+=pos&-pos;
}
}
bool cmp(node a,node b)
{
return a.val<b.val;
}
int main()
{
int k,p,a,b,i;
sf("%d%d%d",&n,&k,&p);
for(i=1;i<=n;i++)
{
sf("%d",&po[i].val);
po[i].id=i;
}
sort(po+1,po+1+n,cmp);
memset(tree,0,sizeof(tree));
memset(bk,0,sizeof(bk));
for(i=1;i<=n;i++) loc[po[i].id]=i;
update(1,1);
for(i=2;i<=n;i++)
if(po[i].val-po[i-1].val<=k)
bk[i]=1,update(i,1);
while(p--)
{
sf("%d%d",&a,&b);
a=loc[a],b=loc[b];
if(a>b) swap(a,b);
if(read(b)-read(a-1)==b-a+1) pf("Yes\n");
else
{
if(!bk[a]&&read(b)-read(a)==b-a) pf("Yes\n");
else pf("No\n");
}
}
return 0;
}
E题:Dish Owner
模板简单并查集
直接上代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define sf scanf
#define pf printf
using namespace std;
const int N=5+1e4;
int s[N],fa[N];
int root(int x){
if(x==fa[x]) return x;
else return fa[x]=root(fa[x]);
}
int main()
{
int T,Q,n,x,y,i,type;
sf("%d",&T);
while(T--)
{
sf("%d",&n);
for(i=1;i<=n;i++) sf("%d",&s[i]),fa[i]=i;
sf("%d",&Q);
while(Q--)
{
sf("%d",&type);
if(!type){
sf("%d%d",&x,&y);
int tx=root(x),ty=root(y);
if(tx==ty) pf("Invalid query!\n");
else if(s[tx]>s[ty]) fa[ty]=tx;
else if(s[tx]<s[ty]) fa[tx]=ty;
else continue;
}
else{
sf("%d",&x);
pf("%d\n",root(x));
}
}
}
return 0;
}
后面的题随后更新:::