2023 ICPC Gran Premio de Mexico 1ra Fecha

待更新

目录

1 A Aliases

Bucket storing

Dynamic Collection

Employees Bonus

Growing game

Jumping Reaction

  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是一个整数,将按顺序应用以下规则:

  1. 如果元素k已在集合中,集合保持不变。

  2. 如果元素k大于集合中的任何元素,则将其添加到集合中。

  3. 最小元素的首次出现大于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;
	}
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值