打完十场回顾一下之前一些的题 都是简单题 难的我不会
继续努力
Luxury cruise ship
纯签到 完全背包。数据有点大。三个物品价值是互质的,我们把7,31,365乘起来,用n%(7*31*365),计算dp[n]+n/(7*31*365)*31*365即可
#include <bits/stdc++.h> #define int long long using namespace std; const int N = 365 * 31 * 7+1; int dp[N], w[4] = { 0,7,31,365 }; int n; signed main() { ios::sync_with_stdio(false); fill(dp, dp + 365 * 31 * 7+1, 0x3f3f3f3f); dp[0] = 0; for (int i = 1; i <= 3; i++) { for (int j = w[i]; j <= N; j++) dp[j] = min(dp[j], dp[j - w[i]] + 1); } int t; cin >> t; while (t--) { cin >> n; int t = n % (365 * 31 * 7); if (dp[t] == 0x3f3f3f3f) cout << -1 << endl; else cout << dp[t] + n / (365 * 31 * 7) * 31 * 7 << endl; } }
Package Delivery
贪心 堆优化
当一个快递到达截至时间时,可取快递小于等于k个,那我们直接全部取出即可。大于k个,那么我们取出最紧急(就是r最小)的k个。
对l,r都有一个贪心的过程,先对l再对r。
#include<bits/stdc++.h> using namespace std; const int N=400010; typedef pair<int,int> PII; int l[N],r[N]; struct node{ int l,r; }p[N]; bool cmp(node a,node b) { return a.l<b.l; } void solve() { int n,k; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d%d",&p[i].l,&p[i].r); sort(p+1,p+n+1,cmp); priority_queue<PII,vector<PII>,greater<PII> >q; while(!q.empty()) q.pop(); q.push({p[1].r,p[1].l}); int t=p[1].r,ans=0; for(int i=2;i<=n;) { while(i<=n&&(p[i].l<=t||t==-1)) { if(t==-1) t=p[i].r; t=min(t,p[i].r); q.push({p[i].r,p[i].l}); i++; } if(!q.empty()) { ans++; if(q.size()<=k){ while(!q.empty()) q.pop(); t=-1; } else{ int tt=k; while(tt--) q.pop(); t=q.top().first; } } } ans+=(q.size()+k-1)/k; printf("%d\n",ans); } signed main() { int _; cin>>_; while(_--) { solve(); } }
Climb Stairs
这个题数据其实比较水(非常水) 官方题解是线段树 其实以这个题的数据之弱 直接暴力枚举加一个前缀和判断来剪枝就能过 全场都过直接做成签到题~
容易看出贪心做法(证明略) 就是往回跳的过程的判断 不能暴力枚举 线段树来维护优化能做(O(nlogn)) 用dp的思想也能维护出 而且更快(O(n)) 暴力加简单的剪枝也能过.......
随便搞的暴力+剪枝code(再吐槽一下数据真的拉):
#include<bits/stdc++.h> #define int long long using namespace std; int read(int &n){ char ch=' '; int q=0,w=1; for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar()); if(ch=='-')w=-1,ch=getchar(); for(;ch>='0'&&ch<='9';ch=getchar())q=q*10+ch-48; n=q*w; return n; } const int N=1e5+10; int n,k,a[N]; int f[N]; void sovle() { read(n); read(a[0]); read(k); f[0]=a[0]; for(int i=1;i<=n;i++){ read(a[i]); f[i]=f[i-1]+a[i]; } int F=1; int sum=a[0]; for(int i=1;i<=n;i++){ if(sum>=a[i]){ sum+=a[i]; } else{ int F2=0; int len1=-1; if(k>=n-i+1){ k=n-i+1; } for(int j=2;j<=k;j++){ int cnt=sum; if(cnt+f[i+j-1]-f[i] < a[i]){ continue; } F2=1; len1=j; for(int k0=i+j-1;k0>=i;k0--){ if(cnt>=a[k0]){ cnt+=a[k0]; } else{ F2=0; break; } } if(F2)break; } if(F2){ sum += f[i+len1-1]-f[i-1]; i += len1-1; } else{ F=0; break; } } } if(F)cout<<"YES"<<endl; else cout<<"NO"<<endl; } signed main(){ int t; read(t); while(t--){ sovle(); } }
Planar graph
是一个删边的题目,删完之后是一个没有环的最大连通子图,没错这就是树。求删边,我们反过来需要留下的边构成最小生成树。那么不留下的就是要删的边了,由于要删字典序最小,我们从字典序更大的开始添加边。
#include<bits/stdc++.h> using namespace std; const int N=2e6+10; int f[N],u[N],v[N]; stack<int>st; int n,m; int find(int x) { return f[x]==x?x:f[x]=find(f[x]); } void sovle() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) scanf("%d%d",&u[i],&v[i]); for(int i=m;i>=1;i--) { int fx=find(u[i]),fy=find(v[i]); if(fx==fy) st.push(i); else f[fx]=fy; } printf("%d\n",st.size()); while(!st.empty()) { printf("%d ",st.top()); st.pop(); } puts(""); } signed main() { int _; cin>>_; while(_--) { sovle(); } }
Link is as bear
求操作过后的最大值,其实等价于求取x个数,x<=n,使得异或和最大,就是一个线性基的常规用法。
此题卡常,不要用c++输入输出 ,用快读或c的输入输出都可。
#include <bits/stdc++.h> #define int long long using namespace std; const int N=1e5+10; int n; int d[110],a[N]; void add(int x) { for(int i=60;i>=0;i--) { if(x&(1ll<<i)) { if(d[i]) x^=d[i]; else { d[i]=x; break; } } } } void sovle() { scanf("%d",&n); memset(d,0,sizeof d); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); add(a[i]); } int ans=0; for(int i=60;i>=0;i--) if((ans^d[i])>ans) ans=ans^d[i]; printf("%lld\n",ans); } signed main() { int _; cin>>_; while(_--) { sovle(); } }
Even Tree Split
签到dfs ,题意是把树分割成偶数节点的集合,从根跑一遍dfs回溯的时候数组记录每个节点的子树节点数+1(加1是自身也算),是偶数满足分割的条件,最后组合起来就是2^cnt-1。(组合数学 集合论)
此题卡常,用vector会被卡,输入输出不要用c++,时间复杂度快到极限时(10^8级别),就不要用一些效率低的写法了。
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e5+5,mod=998244353; int h[N],e[2*N],ne[2*N],idx; int n; int c[N]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} return x*f; }
void add(int a,int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
void init() { for(int i=0;i<N;i++) c[i] = 1; n = read(); int u,v; for(int i=1;i<=n-1;i++){ u = read(), v = read(); add(u,v), add(v,u); } } int pow_mod(int a, int n, int m) { long long ans = 1; while(n){ if(n&1){ ans = (ans * a) % m; } a = (a * a) % m; n >>= 1; } return ans; } void dfs(int x,int fa) { // for(auto y:g[x]){ // if(y==fa) // continue; // dfs(y,x); // c[x]+=c[y]; // } for(int i = h[x]; ~i; i = ne[i]) { int j = e[i]; if(j == fa) continue; dfs(j,x); c[x] += c[j]; } } void sovle() { int cnt=0; for(int i=2;i<=n;i++){ if(c[i]%2==0){ cnt++; } } printf("%lld\n",pow_mod(2,cnt,mod)-1); } signed main() { int _; _ = read(); while(_--){ memset(h, -1, sizeof h); idx = 0; init(); if(n<4){ printf("0\n"); continue; } dfs(1,0); sovle(); } }
(努力更新中 这几天能写的会全部补完)
除了一些不想补的 和对我来说太难的