目录
信息工程大学第五届超越杯程序设计竞赛(同步赛)_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ
A.遗失的旋律
C.财政大臣
D.实验室有多少人
E.在雾中寻宁静
F.不规则的轮回
G.完美数字
M.Monika's game
A.遗失的旋律
思路:模拟即可
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define fs first
#define sc second
#define all(x) x.begin(),x.end()
typedef long long ll;
typedef pair<int,int> PII;
const int mod = 998244353;
int main()
{
cin.tie(0);cout.tie(0);
ios::sync_with_stdio(0);
int n,q;
cin>>n>>q;
string s;
cin>>s;
while(q--)
{
int op;
cin>>op;
if(op==1)
{
int y;cin>>y;
s[y-1]^=1;
}
else
{
int x,l,r;
cin>>x>>l>>r;
l--,r--;
for(int i=l;i<=r;i++)
{
if(s[i]=='0')x=(x+1)%mod;
else x=(2*x)%mod;
}
cout<<x<<endl;
}
}
return 0;
}
C.财政大臣
思路:用邻接表来存图,用数组存每个点的money,每次有变动从根结点dfs一下,记录变化值。
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define fs first
#define sc second
#define all(x) x.begin(),x.end()
typedef long long ll;
typedef pair<int,int> PII;
const int N = 1e5+10,M = 2*N;
int e[M],ne[M],h[N],idx;
int n,m;
int v[N];//记录每个城市的money
ll range[N];//变化值
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa)//fa表示父亲,不能向上搜索;s表示当前这个结点的变化量(从根结点向下累加)
{
range[u]+=range[fa];
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(j!=fa)dfs(j,u);
}
}
void solve()
{
memset(h,-1,sizeof(h));
cin>>n>>m;
for(int i=0;i<n-1;i++)
{
int a,b;cin>>a>>b;
add(a,b),add(b,a);
}
for(int i=1;i<=n;i++)
{
int x;cin>>x;
v[i]=x;
}
while(m--)
{
int op,u,x;
cin>>op>>u>>x;
if(op==1)range[u]+=x;
else range[u]-=x;
}
dfs(1,0);
for(int i=1;i<=n;i++)cout<<v[i]+range[i]<<" ";
}
int main()
{
cin.tie(0);cout.tie(0);
ios::sync_with_stdio(0);
solve();
return 0;
}
D.实验室有多少人
思路:用pair维护信息,排序然后遍历即可,1为到达,2为离开
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define fs first
#define sc second
#define all(x) x.begin(),x.end()
typedef long long ll;
typedef pair<int,int> PII;
const int N = 1e6+10;
bool cmp(PII a,PII b)
{
if(b.fs==a.fs)return a.sc<b.sc;
return a.fs<b.fs;
}
void solve()
{
int n;
cin>>n;
vector<PII> b;
for(int i=0;i<n;i++)
{
int st,ed;
cin>>st>>ed;
b.push_back({st,1});
b.push_back({ed,2});
}
sort(all(b),cmp);
int ans=0,cnt=0;
for(auto x:b)
{
if(x.sc==1)cnt++;
else cnt--;
ans=max(ans,cnt);
}
cout<<ans<<endl;
}
int main()
{
cin.tie(0);cout.tie(0);
ios::sync_with_stdio(0);
int t=1;
while(t--)
{
solve();
}
return 0;
}
E.在雾中寻宁静
思路:正序dfs即可完成覆盖
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define fs first
#define sc second
#define all(x) x.begin(),x.end()
typedef long long ll;
typedef pair<int,int> PII;
const int N = 2e5+10, M = 2*N;
int e[M],ne[M],h[N],idx;
int n,q,col[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int color)
{
col[u]=color;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
dfs(j,color);
}
}
void solve()
{
memset(h,-1,sizeof(h));
cin>>n;
for(int i=1;i<=n-1;i++)
{
int x;cin>>x;
add(x,i+1);
}
cin>>q;
vector<PII> a(q);
for(int i=0;i<q;i++)
{
int x,y;
cin>>x>>y;
a[i]={x,y};
}
for(int i=0;i<q;i++)
{
int x=a[i].fs,y=a[i].sc;
dfs(x,y);
}
for(int i=1;i<=n;i++)cout<<col[i]<<" ";
}
int main()
{
cin.tie(0);cout.tie(0);
ios::sync_with_stdio(0);
int t=1;
while(t--)
{
solve();
}
return 0;
}
F.不规则的轮回
思路:模拟,O(1)查询
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define fs first
#define sc second
#define all(x) x.begin(),x.end()
typedef long long ll;
typedef pair<int,int> PII;
const int N = 1e4+10;
int a[N][N];
void solve()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
int x,y;
cin>>x>>y;
a[x][y]++;
while(x!=y)
{
if(x>y)x-=y;
else if(x<y)y-=x;
a[x][y]++;
}
}
int q;
cin>>q;
while(q--)
{
int qx,qy;
cin>>qx>>qy;
cout<<a[qx][qy]<<endl;
}
}
int main()
{
cin.tie(0);cout.tie(0);
ios::sync_with_stdio(0);
int t=1;
while(t--)
{
solve();
}
return 0;
}
G.完美数字
思路:考虑10的因子是2和5,也就是两个数字含有2,5因子的乘积可以构成10,那么min(t2,t5)就是10的个数,也就是0的个数.
copy一下好的题解qaq
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define fs first
#define sc second
#define all(x) x.begin(),x.end()
typedef long long ll;
typedef pair<int,int> PII;
const int N = 2e5+10;
int a[N],a2[N],a5[N];
int sum2[N],sum5[N];//遍历区间要用到区间内的因子数量
ll res;
void cal(int x,int i)
{
int t=x;
while(t%2==0)t/=2,a2[i]++;
t=x;
while(t%5==0)t/=5,a5[i]++;
}
void solve()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
cal(a[i],i);//统计a[i]中,2和5因子的数量
}
for(int i=1;i<=n;i++)
{
sum2[i]=sum2[i-1]+a2[i];
sum5[i]=sum5[i-1]+a5[i];
}
for(int l=1;l<=n;l++)
{
for(int r=l;r<=n;r++)//一个区间可以有1个数,所以r可以从l开始
{
int t2=sum2[r]-sum2[l-1];
int t5=sum5[r]-sum5[l-1];
int sum=min(t2,t5);
if(sum>=k)//如果成立,那么把他后面的数字加上去也成立,所以区间数量为n-r+1
{
res+=n-r+1;
break;
}
}
}
cout<<res<<endl;
}
int main()
{
cin.tie(0);cout.tie(0);
ios::sync_with_stdio(0);
int t=1;
while(t--)
{
solve();
}
return 0;
}
M.Monika's game
思路:n*(n-1)/2
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
long long t, n;
long long summ;
cin >> t;
for(int i = 1; i <= t; i++){
cin >> n;
summ = n*(n-1)/2;
printf("%lld\n", summ);
}
return 0;
}