待更新
目录
1 A Aliases
A Aliases
题意:给你一系列字符串每个字符串的名字等于字符串之间每个单词的首字母 问你有多少唯一名字题解 :开给map存一下 如果重复减去就行了
# include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);
#define endl '\n'
# define int long long
map<string,int>s;
map<string,int>d;
signed main()
{
IOS
int t;
int res=0;
cin>>t;
while(t--)
{
int n;
cin>>n;
string s2="";
for(int i=1; i<=n; i++)
{
string s1;
cin>>s1;
s2+=s1[0];
}
if(!s[s2])
{
res+=1;
s[s2]=1;
}
else if(!d[s2])
{
res-=1;
d[s2]=1;
}
}
cout<<res<<endl;
}
B Bucket storing
签到
# include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);
#define endl '\n'
# define int long long
signed main()
{
IOS
int n,k,l;
cin>>n>>k>>l;
int res=n*k;
int res1=0;
if(res%l!=0)
{
res1=res/l+1;
}
else
{
res1=res/l;
}
cout<<res1<<endl;
}
D Dynamic Collection
题意:
对于操作2,a和b
是定义一个范围的两个整数。此操作的目的是查询集合中有多少元素属于这个范围(包括范围)。对于操作 1,k是一个整数,将按顺序应用以下规则:
如果元素k已在集合中,集合保持不变。
如果元素k大于集合中的任何元素,则将其添加到集合中。
最小元素的首次出现大于k替换为k。
题解:利用stl对于操作1可以替换序列K
对于操作二求第一个大于等于a的坐标和第一个小于等于b的坐标即可
# include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);
#define endl '\n'
# define int long long
const int N=3e6+10;
map<int,int>d;
int a[N];
signed main()
{
IOS
int n,q;
cin>>n>>q;
for(int i=1; i<=n; i++)
{
cin>>a[i];
d[a[i]]++;
}
sort(a+1,a+n+1);
while(q--)
{
int op;
cin>>op;
if(op==1)
{
int k;
cin>>k;
if(!d[k])
{
if(k>a[n])
{
a[++n]=k;
}
else
{
int i=lower_bound(a+1,a+n+1,k)-a;
d[a[i]]--;
a[i]=k;
}
d[k]++;
}
}
else
{
int c,d;
cin>>c>>d;
int i=lower_bound(a+1,a+n+1,c)-a;
int y=upper_bound(a+1,a+n+1,d)-a;
y-=1;
if(y>=i)
{
cout<<y-i+1<<endl;
}
else
{
cout<<"0"<<endl;
}
}
}
}
E Employees Bonus
题意:
Acme公司有一种特殊的奖金分配方式:当一名员工收到本部门的奖金时,他们将其平均分配给直接或间接受其指挥的所有员工(包括他们自己)。如果奖金金额不能平均分配给所有下属,则部门主管保留剩余部分。公司已经收到奖金将根据上述政策分配给员工。每个员工都有一定数量的钱,他们认为这是经济上的成功。您的任务是确定每个员工的第一笔奖金(即奖金在Q序列中的顺序号)
他们获得经济上成功的奖金。题解:有题可知我们所需要的操作是一个区间修改该员工和他下属的钱
所以建立一个线段树维护即可
# include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);
#define endl '\n'
# define int long long
# define lc cur<<1
# define rc cur<<1|1
const int N=1e5+10;
vector<int>g[N];
int in[N],out[N];
int id[N];
int book[N];
int ans[N];
int tot=0;
int a[N];
void dfs(int u)
{
in[u]=++tot;
id[tot]=u;
for(auto i:g[u])
{
dfs(i);
}
out[u]=tot;
}
struct stu
{
int val,tag;
}tree[N<<2];
void build(int cur,int l,int r)
{
if(l==r)
{
tree[cur].val=a[id[l]];
return ;
}
int mid=(l+r)>>1;
build(lc,l,mid);
build(rc,mid+1,r);
tree[cur].val=min(tree[lc].val,tree[rc].val);
}
void pushdown(int cur)
{
tree[lc].tag+=tree[cur].tag;
tree[rc].tag+=tree[cur].tag;
tree[lc].val+=tree[cur].tag;
tree[rc].val+=tree[cur].tag;
tree[cur].tag=0;
}
void update(int cur,int l,int r,int a,int b,int y)
{
if(a<=l&&r<=b)
{
tree[cur].tag+=y;
tree[cur].val+=y;
return ;
}
pushdown(cur);
int mid=(l+r)>>1;
if(a<=mid)
{
update(lc,l,mid,a,b,y);
}
if(b>mid)
{
update(rc,mid+1,r,a,b,y);
}
tree[cur].val=min(tree[lc].val,tree[rc].val);
}
void solve(int cur,int l,int r,int t)
{
if(tree[cur].val>0)
{
return ;
}
if(l==r)
{
ans[id[l]]=t;
tree[cur].val=1e18;
return ;
}
pushdown(cur);
int mid=(l+r)>>1;
solve(lc,l,mid,t);
solve(rc,mid+1,r,t);
tree[cur].val=min(tree[lc].val,tree[rc].val);
}
signed main()
{
IOS
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
ans[i]=-1;
}
for(int i=1;i<=n-1;i++)
{
int u,v;
cin>>u>>v;
g[u].push_back(v);
book[v]++;
}
for(int i=1;i<=n;i++)
{
if(!book[i])
{
dfs(i);
}
}
build(1,1,n);
for(int i=1;i<=q;i++)
{
int x,y;
cin>>x>>y;
int z=y/(out[x]-in[x]+1);
if(in[x]!=out[x])
{
update(1,1,n,in[x]+1,out[x],-z);
}
z+=y%(out[x]-in[x]+1);
update(1,1,n,in[x],in[x],-z);
solve(1,1,n,i);
}
for(int i=1;i<=n;i++)
{
cout<<ans[i]<<endl;
}
}
G Growing game
题意:每个人都可以拿筹码的有趣方式是,在第一轮(简的回合)她只能拿1个筹码,在第二轮(约翰的回合)他可以选择拿1个或2个筹码,在第三轮(简的回合)她可以选择拿1个、2个或3个筹码。一般来说,在第i回合中,玩家应该轮流获得至少1个问拿走最后一个筹码的是谁
题解:没想到啥易理解的方法,纯属找规律
设JiAN win 为0
否则为1
筹码从1到11的胜者如下:
0 1 1 0 0 1 1 1 0 0 0
# include <bits/stdc++.h>
using namespace std;
const int N=5001;
int a[N];
int main() {
int ans=1;
int flag=1;
int res=1;
for(int i=1; i<=5000; i++) {
a[i]=flag;
ans--;
if(ans==0) {
if(flag) {
res++;
flag=0;
ans=res;
}
else
{
ans=res;
flag=1;
}
}
}
int t;
cin>>t;
if(a[t])
{
cout<<"Jane"<<endl;
}
else
{
cout<<"John"<<endl;
}
}
J Jumping Reaction
题意:给你一个序列 然后再给你一个区间l,r
问你求 l*l+1,l*l+2....r-1*r的和
题解 :因为该题有多个提问所以利用前缀和进行维护
第一个前缀和为从1到i的1*2,......(i-1)*i的和
第二个前缀和为从1到i的1*2,1*3,1*n...,i*n的和
设sum为第一个前缀和序列,sum1为第二个前缀和序列,设sum2为前i个数字的和序列
则区间l,r的答案为:sum[r]-sum1[l-1]+sum2[l-1]*(sum2[n]-sum2[r])
该题要求要取模所以求值注意一下负数取模即可
# include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);
#define endl '\n'
# define int long long
int n,q;
const int mod=1e9+7;
const int N=1e6+10;
int a[N];
__int128 sum[N];
__int128 sum1[N];
__int128 sum2[N];
int sum3[N];
signed main()
{
IOS
cin>>n>>q;
for(int i=1; i<=n; i++)
{
cin>>a[i];
sum1[i]=(sum1[i-1]+sum[i-1]*a[i]%mod)%mod;
sum1[i]%=mod;
sum[i]=(sum[i-1]+a[i])%mod;
sum[i]%=mod;
}
for(int i=1;i<=n;i++)
{
sum2[i]=(sum2[i-1]+((sum[n]-sum[i]))%mod*a[i]%mod)%mod;
sum2[i]%=mod;
}
while(q--)
{
int l,r;
cin>>l>>r;
int res=((sum[n]-sum[r]+mod)%mod*sum[l-1]%mod)%mod;
res%=mod;
res=(res+(((sum1[r]-sum2[l-1])%mod+mod)%mod))%mod;
cout<<res%mod<<endl;
}
}