2024杭电多校第七场
1004
如果r2>2r1且树的直径>2r1,则逃跑方总能逃跑
否则攻击方肯定能一步步把其逼到叶子节点
#include<bits/stdc++.h> using namespace std; const int N=1e5; int n,s,r1,r2; vector<int> ver[N+5]; inline int read() { int x=0;bool f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())f^=(ch=='-'); for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48); return f?x:-x; } int dep[N+5],q[N+5],l,r; int bfs(int st) { int res=st; for(int i=1;i<=n;++i) dep[i]=0; q[l=r=1]=st,dep[st]=1; for(int x;l<=r;) { x=q[l++]; if(dep[x]>dep[res]) res=x; for(auto y:ver[x]) { if(dep[y]) continue; dep[y]=dep[x]+1,q[++r]=y; } } return res; } void Kafka() { n=read(),s=read(),r1=read(),r2=read(); for(int i=1;i<=n;++i) ver[i].clear(); for(int i=1;i<n;++i) { int u=read(),v=read(); ver[u].push_back(v); ver[v].push_back(u); } if(r2<=r1*2) {puts("Kangaroo_Splay");return;} int d=dep[bfs(bfs(s))]-1; if(d<=r1*2) {puts("Kangaroo_Splay");return;} puts("General_Kangaroo"); } signed main() { for(int T=read();T--;)Kafka(); return 0; }
1007
考虑比较裸的线段树优化dp,优化后dp[ a[i] ]为max(dp[ a[i]-k ],dp[ a[i]+k ])+1
这样的时间复杂度是O(q*n*log)的
再考虑怎么优化这个事情,其实决策点并没有一个范围这么大,而是[ a[i]-k,a[i] ]中下标最靠后的点(反证法)
预处理出每个点可以从哪两个点转移
时间复杂度是O(nlogn+nq)
#include<bits/stdc++.h> using namespace std; #define L (p<<1) #define R ((p<<1)|1) #define Mid (l+r>>1) inline int read() { int x=0;bool f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())f^=(ch=='-'); for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48); return f?x:-x; } const int N=1e5+505; long long n,m,k,q; long long a[N]; int l[N],r[N]; map<long long,int> f; struct BIT{ int t[N*4]; void up(int p){ t[p]=max(t[L],t[R]); } void build(int p,int l,int r){ if (l==r){ t[p]=0; return; } int mid=Mid; build(L,l,mid); build(R,mid+1,r); t[p]=t[L]=t[R]=0; } void change(int p,int l,int r,int x,int w){ if (l==r){ t[p]=w; //printf("t[%d]=%d l=%d r=%d x=%d w=%d\n",p,t[p],l,r,x,w); return; } int mid=Mid; if (x<=mid) change(L,l,mid,x,w); else change(R,mid+1,r,x,w); up(p); } int find(int p,int l,int r,int x,int y){ if (l>=x&&r<=y){ return t[p]; } int mid=Mid; int res=0; if (x<=mid) res=max(res,find(L,l,mid,x,min(mid,y))); if (y>mid) res=max(res,find(R,mid+1,r,max(mid+1,x),y)); return res; } }t; void test_tree(){ //for (int i=1;i<=10;i++) //printf("t[%d]=%d\n",i,t.t[i]); for (int i=1;i<=n;i++) printf("dp[%d]=%d\n",i,t.find(1,1,n,i,i)); } int query(int x,int y){ t.build(1,1,n); int res; for (int i=x;i<=y;i++){ if (l[i]>=r[i]) res=0; else res=t.find(1,1,n,l[i],r[i]-1); //test_tree(); //printf("l[i]=%d r[i]-1=%d res=%d\n",l[i],r[i]-1,res); t.change(1,1,n,f[a[i]],res+1); } res=t.find(1,1,n,1,n); return res; } void test(){ for (int i=1;i<=n;i++) cout << l[i] << " " << r[i] << endl; } void work(){ cin >> n >> m >> k; f.clear(); for (int i=1;i<=n;i++){ cin >> a[i]; f[a[i]]=0; } int cnt=0; for (auto i=f.begin();i!=f.end();i++) i->second=++cnt; for (int i=1;i<=n;i++){ l[i]=distance(f.begin(),f.lower_bound(a[i]-k))+1; r[i]=distance(f.begin(),f.upper_bound(a[i]+k))+1; } //test(); cin >> q; for (int i=1;i<=q;i++){ int x,y; cin >> x >> y; cout << y-x+1-query(x,y) << endl; } } signed main() { ios_base::sync_with_stdio(false); cin.tie(0);cout.tie(0); int T; cin >> T; while(T--) work(); return 0; }
1009
树dp完后取代价最大的孩子节点ban掉,实现起来主要注意会不会爆longlong
小技巧是和一个比较大的常数取min
#include<bits/stdc++.h> using namespace std; #define int long long const int N = 1e5+5; const __int128 inf = 2e9+10; int n,k; __int128 t[N],num[N],ans[N]; vector<int>e[N]; void dfs(int u,int p){ if(e[u].size()==0){ ans[u]=t[u]; return; } ans[u]=0;// needed time for(auto v:e[u]){ if(v==p) continue; //cout<<u<<" to "<<v<<"\n"; dfs(v,u); ans[u]+=num[v]*ans[v]; ans[u]=min(ans[u],inf); } } void solve(){ cin>>n>>k; for(int i=1;i<=n;i++) { t[i]=num[i]=0; e[i].clear(); } for(int i=1;i<=n;i++) { int op;cin>>op; if(op==0) { int x;cin>>x; t[i]=x; } else { int tot;cin>>tot; for(int j=1;j<=tot;j++){ int x,a;cin>>x>>a; num[a]=x; e[i].push_back(a); // cout<<i<<" -> "<<a<<"\n"; } } } dfs(k,0); __int128 mx=0; int pos=-1; for(auto v:e[k]){ if(num[v]*ans[v]>mx){ pos=v; mx=num[v]*ans[v]; } } __int128 out=0; for(auto v:e[k]){ if(v==pos) continue; out=out+num[v]*ans[v]; } if(out>(1000000000)) cout<<"Impossible"<<"\n"; else { int final=out; cout<<final<<"\n"; } } signed main() { ios_base::sync_with_stdio(false); cin.tie(0);cout.tie(0); int t;cin>>t; while(t--) solve(); return 0; }
1010
反悔贪心
#include<bits/stdc++.h> using namespace std; const int N = 1e5+5; #define int long long int n,x,k; int a[N]; void solve(){ cin>>n>>x>>k; for(int i=1;i<=n;i++) cin>>a[i]; int use=0; priority_queue<int>q; for(int i=1;i<=n;i++){ x-=a[i]; q.push(a[i]); //cout<<i<<" "<<x<<"\n"; if(x<=0){ while(use<k&&!q.empty()){ x+=q.top(); q.pop(); use++; if(use==k) break; if(x>0) break; } } if(x<=0) { cout<<i-1<<"\n"; return; } } cout<<n<<"\n"; } signed main() { ios_base::sync_with_stdio(false); cin.tie(0);cout.tie(0); int t; cin>>t; while(t--) solve(); return 0; }
1011
队友做的
#include<bits/stdc++.h> #define int long long using namespace std; inline int read() { int x=0;bool f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())f^=(ch=='-'); for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48); return f?x:-x; } int gcd(int x,int y){return y?gcd(y,x%y):x;} void Kafka() { int x=read(),y=read(),d=gcd(x,y),dx=x/d,dy=y/d; if(dy==1) {printf("%lld %lld\n",y,dx);return;} if(dy&1) {printf("%lld %lld\n",y,dx<<1LL);return;} else {printf("%lld %lld\n",y,dx);return;} } signed main() { for(int T=read();T--;) Kafka(); return 0; }
1008
考虑矩阵快速幂优化
#include<bits/stdc++.h> using namespace std; const int N = 100; const int mod = 1e9+7; typedef long long ll; int n,m; ll l,r; struct Mat{ int a[N+5][N+5]; void init( ){ memset(a,0,sizeof a); } void one(int n){ memset(a,0,sizeof a); for(int i=1;i<=n;i++) a[i][i]=1; } Mat operator * (Mat b){ Mat c; c.init(); for(int i=1;i<=n+1;i++) for(int j=1;j<=n+1;j++) for(int k=1;k<=n+1;k++) c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j]%mod)%mod; // cout<<"Mat c:"<<"\n"; // c.print(); return c; } void print(){ for(int i=1;i<=n+1;i++){ for(int j=1;j<=n+1;j++){ cout<<a[i][j]<<" "; } cout<<"\n"; } } }; Mat qpow(Mat c,ll x){ Mat ret;ret.one(n+1); while(x){ if(x&1) ret=ret*c; c=c*c; x>>=1; // cout<<x<<"\n"; // cout<<"Mat: c"<<"\n"; // c.print(); } return ret; } ll work(Mat p,ll x,Mat o){ ll t=x/n; ll r=x%n; //cout<<"t:"<<t<<"\n"; p=qpow(p,t); ll ret=p.a[1][n+1]; p=p*o; //cout<<"????"<<"\n"; for(int i=1;i<=r;i++) ret=(ret+p.a[1][i])%mod; //cout<<x<<" ret:"<<ret<<"\n"; return ret; } void solve(){ cin>>n>>m>>l>>r; Mat o,o1,o2,p; o.init(); o1.init(); o2.init(); for(int i=1;i<=n+1;i++) o2.a[i][n+1]=1; for(int i=1,u,v,w;i<=m;i++){ cin>>u>>v>>w; if(u<=n&&v<=n) o1.a[u][v]=w; else o2.a[u][v-n]=w; } // dp 一次 o.one(n+1); for(int i=n;i>=1;i--) for(int j=i;j<=n;j++) for(int k=j;k<=n;k++) o.a[i][k]=(o.a[i][k]+1ll*o.a[i][j]*o1.a[j][k]%mod)%mod; // 行间的转移 /* cout<<"Mat o:"<<"\n"; o.print(); cout<<"Mat o2:"<<"\n"; o2.print(); */ p=o*o2; /* cout<<"Mat p:"<<"\n"; p.print(); */ cout<<(work(p,r,o)-work(p,l-1,o)+mod)%mod<<"\n"; } /* 2 3 4 5 6 1 2 1 1 3 1 3 4 1 2 5 1 5 8 998244353 1000000007 1 2 114514 1 4 1919810 2 3 999999999 3 5 111111111 4 5 1000000000 1 10 123456789 5 6 987654321 3 9 888888888 */ int main(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t;cin>>t; while(t--){ solve(); } }