Dashboard - 2022 CCPC Henan Provincial Collegiate Programming Contest - Codeforces
- #include
- using namespace std;
- #define ll long long
- #define endl "\n"
- const int mod=998244353;
- const int N=2e5+50;
- ll a[N],d[30],dp[N],pre[20];
- void mysolve()
- {
- string s;
- cin>>s;
- int n=s.size();
- for(int i=0; i
- {
- if(s[i]=='a')a[i]=1;
- else if(s[i]=='e')a[i]=2;
- else if(s[i]=='h')a[i]=3;
- else a[i]=4;
- }
- ll ans=0;
- pre[0]=1;
- for(int i=1; i<=13; ++i)pre[i]=pre[i-1]*31%mod;
- for(int k=0; k<13; ++k)//枚举开头
- {
- vector
dp(n+15); - int l=k,r=n+l-1;
- a[r+1]=a[l];//因为开头移动,所以尾部也移动了
- for(int i=l; i<=r; ++i)//遍历dp[i]
- {
- ll tmp=0;
- for(int j=0; j<14&&i-j>=l; ++j)//枚举以i结尾的最优长度获取dp[i]
- {
- tmp=(tmp+a[i-j]*pre[j])%mod;
- if(i-j)dp[i]=max(dp[i],dp[i-j-1]+tmp);
- }
- }
- ans=max(ans,dp[r]);
- }
- cout<
- }
-
- int32_t main()
- {
- std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
- mysolve();
- return 0;
- }
Problem C. Serval 的试卷答案
思路:
- 对于s[i]>s[i+1]的,显然我们必须把他们隔开。
- 而我们需要获取k段,显然需要插k-1个隔板,如果我们把必须隔开的隔开后,剩下可以插空的位置就是可以容易插。所以对于一段[l,r]划分k段,要求必须划分的有cnt段。答案就是组合数
,显然我们线段树维护好cnt即可
- #include
- using namespace std;
- #define ll long long
- #define endl "\n"
- const int N = 1e5 + 20;
- const int mod=998244353;
- int a[N];
- int n,q;
- #define ls p<<1
- #define rs p<<1|1
- #define mid (t[p].l+((t[p].r-t[p].l)>>1))
- ll pre[N],dev[N],tmp[4][4];
- struct tree
- {
- int l,r;
- int ld,rd;
- int add,cnt;
- int sum[4][4];
- } t[N<<2];
-
- inline ll fastmi(ll base,ll power)
- {
- ll ans=1;
- while(power)
- {
- if(power&1)ans=ans*base%mod;
- base=base*base%mod;
- power>>=1;
- }
- return ans;
- }
-
- inline void pushup(int p)
- {
- for(int i=0; i<4; ++i)for(int j=0; j<4; ++j)t[p].sum[i][j]=t[ls].sum[i][j]+t[rs].sum[i][j];
- t[p].sum[t[ls].rd][t[rs].ld]++;
- t[p].ld=t[ls].ld,t[p].rd=t[rs].rd;
- t[p].cnt=t[ls].cnt+t[rs].cnt;
- if(t[ls].rd>=t[rs].ld)t[p].cnt++;
- }
-
- void build(int l,int r,int p)
- {
- t[p].l=l,t[p].r=r;
- if(t[p].l==t[p].r)
- {
- t[p].ld=t[p].rd=a[l];
- return;
- }
- build(l,mid,ls),build(mid+1,r,rs);
- pushup(p);
- }
-
- inline void change(int p,int w)
- {
- for(int i=0; i<4; ++i)for(int j=0; j<4; ++j)tmp[i][j]=t[p].sum[i][j];
- for(int i=0; i<4; ++i)for(int j=0; j<4; ++j)t[p].sum[(i+w)%4][(j+w)%4]=tmp[i][j];
- t[p].ld=(t[p].ld+w)%4,t[p].rd=(t[p].rd+w)%4;
- t[p].cnt=0;
- for(int i=0; i<4; ++i)for(int j=i; ~j; --j)t[p].cnt+=t[p].sum[i][j];
- t[p].add+=w;
- }
-
- inline void lazy(int p)
- {
- if(t[p].l==t[p].r)t[p].add=0;
- if(t[p].add)
- {
- change(ls,t[p].add),change(rs,t[p].add);
- t[p].add=0;
- }
- }
-
- void update(int l,int r,int p)
- {
- if(l<=t[p].l&&t[p].r<=r)
- {
- change(p,1);
- return;
- }
- lazy(p);
- if(mid>=l)update(l,r,ls);
- if(mid
update(l,r,rs); - pushup(p);
- }
-
- int ask(int l,int r,int p)
- {
- if(l<=t[p].l&&t[p].r<=r)return t[p].cnt;
- int ans=0;
- lazy(p);
- if(mid>=l)ans+=ask(l,r,ls);
- if(mid
ask(l,r,rs); - if(l<=mid&&mid
=t[rs].ld); - return ans;
- }
-
- inline ll C(int n,int m)
- {
- if(m>n||m<0||n<0)return 0;
- return 1ll*pre[n]*dev[m]%mod*dev[n-m]%mod;
- }
-
- void mysolve()
- {
- cin>>n>>q;
- string s;
- cin>>s;
- for(int i=0; i
1]=s[i]-'A'; - build(1,n,1);
- int l,r,k,op;
- while(q--)
- {
- cin>>op>>l>>r;
- if(op==1)update(l,r,1);
- else
- {
- cin>>k;
- int cnt=ask(l,r,1);
- cout<<C(r-l-cnt,k-1-cnt)<
- }
- }
- }
-
- int32_t main()
- {
- std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
- pre[0]=1;
- int nx=1e5;
- for(int i=1; i<=nx; ++i)pre[i]=pre[i-1]*i%mod;
- dev[nx]=fastmi(pre[nx],mod-2)%mod;
- for(int i=nx-1; ~i; --i)dev[i]=dev[i+1]*(i+1)%mod;
- mysolve();
- system("pause");
- return 0;
- }
Problem J. Mex Tree
思路:
- 如果mex=n,显然答案为n
- 我们以val[i]=0的i设为根rt
- 显然mex=0时答案就是根节点的最大子树
- 其他情况,mex=k,显然val[i]=k的点不能包含,又必须包含小于k的所有点,显然我们答案就是取除k的子树之外的所有点(因为0点为根节点,k子树内的点与0相连必须经过k),如果k子树内存在点小于k,那么答案为0,如果都大于k,那么答案为n-sz[k](k子树大小)
- 因此,我们需要维护每个点的子树的包含的最小值
- #include
- using namespace std;
- #define ll long long
- #define endl "\n"
- #define int long long
- typedef pair<int, int> pii;
- //---------------------------------------------------------------------------------------------------------------------//
- //---------------------------------------------------------------------------------------------------------------------//
- //double 型memset最大127,最小128
- const int INF = 0x3f3f3f3f; //int型的INF
- const ll llINF = 0x3f3f3f3f3f3f3f3f;//ll型的llINF
- const double eps=1e-9;
- const int N = 1e6 + 10;
- int a[N],sz[N],mn[N],mx[N],b[N];
- vector<int>edge[N];
- void dfs(int u,int f)
- {
- sz[u]=1,mn[u]=a[u];
- mx[u]=0;
- for(auto v:edge[u])if(v!=f)
- {
- dfs(v,u);
- mx[u]=max(mx[u],sz[v]);
- sz[u]+=sz[v];
- mn[u]=min(mn[u],mn[v]);
- }
- }
- void mysolve()
- {
- int n;
- cin>>n;
- int rt;
- for(int i=1; i<=n; ++i)
- {
- cin>>a[i];
- b[a[i]]=i;
- if(a[i]==0)rt=i;
- }
- int x;
- for(int i=2; i<=n; ++i)cin>>x,edge[x].push_back(i),edge[i].push_back(x);
- dfs(rt,-1);
- cout<
" "; - for(int i=1; i
- {
- if(mn[b[i]]>=i)cout<
" "; - else cout<<"0 ";
- }
- cout<
- }
-
- int32_t main()
- {
- std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
- ll t=1;
- //cin >> t;
- while (t--)
- {
- mysolve();
- }
- system("pause");
- return 0;
- }
-
相关阅读:
shell 实例:检查default路由的存在
2021第7届中国大学生程序设计竞赛CCPC广州站, 签到题4题
Mybatis快速上手
Linux用户/用户组管理
branch与tag
精英反向黄金正弦鲸鱼算法-附代码
Vue项目的部署(服务器)
16位、32位、64位系统字节长度
喜报 | 祝贺璞华科技通过CMMI Lv5 等级复审!
【LeetCode】891.子序列宽度之和
-
原文地址:https://blog.csdn.net/WQhuanm/article/details/130845216