2020 寒假 Day3
icpc上海-M-Gitignore
更简单的做法是:记录m个要保留的路径,把每个子路径都标记不能删除,然后暴力枚举n个字符串的路径,如果一个必须要删除的文件的子路径没有被标记,那么直接删除这个文件的当前子路径即可。
#include <bits/stdc++.h> using namespace std; #define pb push_back typedef long long ll; const int N=1e5+500; map<string,int>mp; string s[200]; int main(){ int t;cin>>t; while(t--){ mp.clear(); int n,m;cin>>n>>m; for(int i=1;i<=n+m;i++)cin>>s[i]; for(int i=n+1;i<=n+m;i++){ string ss=""; for(int j=0;j<s[i].size();j++){ ss+=s[i][j]; if(s[i][j]=='/')mp[ss]=1; } } int ans=n; for(int i=1;i<=n;i++){ string ss=""; for(int j=0;j<s[i].size();j++){ ss+=s[i][j]; if(s[i][j]=='/'){ if(mp[ss]==0)mp[ss]=2; else if(mp[ss]==1)continue; else {ans--;break;} } } } cout<<ans<<endl; } // system("pause"); return 0; }
B - Repository
模拟搜索过程,对每个字符串的后缀都建立一颗字典树,用一个belong数组标记同一个字符串的前缀,当belong发生变化时更新cnt数组, 那么查询时直接输出即可。
但数组要开到5e5左右。
#include<bits/stdc++.h> using namespace std; const int N=5e5+500; int trie[N][30]; int tot; int belong[N],cnt[N]; void insert(char s[],int x){ int len=strlen(s); int p=0; for(int i=0;i<len;i++){ int n=s[i]-'a'; if(trie[p][n]==0)trie[p][n]=++tot; p=trie[p][n]; if(belong[p]!=x)cnt[p]++; belong[p]=x; } } int find(char s[]){ int len=strlen(s); int p=0; for(int i=0;i<len;i++){ int n=s[i]-'a'; if(trie[p][n]==0)return 0; p=trie[p][n]; } return cnt[p]; } int main(){ int p;cin>>p; tot=0; memset(belong,0,sizeof belong); memset(trie,0,sizeof trie); memset(cnt,0,sizeof cnt); getchar(); for(int i=1;i<=p;i++){ char s[30]; scanf("%s",s); int len=strlen(s); for(int j=0;j<len;j++){ insert(s+j,i); } } int q;cin>>q; while(q--){ char s[30];scanf("%s",s); // cout<<"test : "; printf("%d\n",find(s)); } // system("pause"); return 0; }
A - T-shirt buying
#include<bits/stdc++.h> using namespace std; const int N=5e5+500; typedef long long ll; ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} int a[N],b[N],p[N]; struct node{ int id,p; friend bool operator<(node a,node b){ return a.p>b.p; } }; // priority_queue<node>Q[3]; set<node>st[4]; int main(){ int n;cin>>n; for(int i=1;i<=n;i++)scanf("%d",&p[i]); for(int i=1;i<=n;i++)scanf("%d",&a[i]),st[a[i]].insert(node{i,p[i]}); for(int i=1;i<=n;i++)scanf("%d",&b[i]),st[b[i]].insert(node{i,p[i]}); int m;cin>>m; while(m--){ int x;scanf("%d",&x); if(st[x].empty())cout<<-1<<" "; else { int u=st[x].rbegin()->id; node tmp;tmp.id=u;tmp.p=p[u]; st[x].erase(tmp); cout<<p[u]<<" "; if(x!=1&&st[1].find(tmp)!=st[1].end())st[1].erase(tmp); if(x!=2&&st[2].find(tmp)!=st[2].end())st[2].erase(tmp); if(x!=3&&st[3].find(tmp)!=st[3].end())st[3].erase(tmp); } } // system("pause");~ return 0; }
C - Oil Skimming
把每一个格子抽出来,直接二分图匹配。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=700; vector<int>G[N]; int n; char s[700][700]; int Hash[700][700]; int vis[N],match[N]; int tot=0; void add(int u,int v){ G[u].push_back(v); G[v].push_back(u); } bool findpath(int u){ for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(!vis[v]){ vis[v]=1; if(!match[v]||findpath(match[v])){ match[v]=u; return true; } } } return false; } int main(){ int t;cin>>t; int kase=0; while(t--){ memset(G,0,sizeof G); memset(match,0,sizeof match); memset(Hash,0,sizeof Hash); cin>>n; tot=0; for(int i=1;i<=n;i++){ getchar(); for(int j=1;j<=n;j++){ scanf("%c",&s[i][j]); if(s[i][j]=='#'){ Hash[i][j]=++tot; } } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(s[i][j]=='#'){ if(i+1<=n&&s[i+1][j]=='#'){ add(Hash[i][j],Hash[i+1][j]); } if(j+1<=n&&s[i][j+1]=='#'){ add(Hash[i][j],Hash[i][j+1]); } } } } int ans=0; for(int i=1;i<=tot;i++){ memset(vis,0,sizeof vis); if(findpath(i))ans++; } ans/=2; printf("Case %d: %d\n",++kase,ans); // Case 1: 3 } // system("pause"); return 0; }
E - String LCM
类似牛客多校,判断两个字符串是否有lcm可以在5*max(lena,lenb) 的时间以内判断出来。
#include<bits/stdc++.h> using namespace std; const int N=5e5+500; typedef long long ll; ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} int main(){ int t;cin>>t; while(t--){ string a,b;cin>>a>>b; int lena=a.size(),lenb=b.size(); int flag=1; for(int i=0;i<=5*max(lena,lenb);i++){ if(a[i%lena]!=b[i%lenb]){ flag=0; break; } } if(!flag)puts("-1"); else { int len=lcm(lena,lenb); for(int i=0;i<len;i++)cout<<a[i%lena]; cout<<endl; } } // system("pause"); return 0; }
A - Two Arrays And Swaps
#include<bits/stdc++.h> using namespace std; const int N=1e5+500; int a[N],b[N]; int main(){ int t;cin>>t; while(t--){ int n,k;cin>>n>>k; int sum=0; for(int i=1;i<=n;i++)scanf("%d",&a[i]),sum+=a[i]; for(int i=1;i<=n;i++)scanf("%d",&b[i]); sort(a+1,a+1+n); sort(b+1,b+1+n); int pos=1; while(pos<=k){ if(a[pos]<b[n-pos+1])sum+=b[n-pos+1]-a[pos]; pos++; } // cout<<"test :"; cout<<sum<<endl; } // system("pause"); return 0; }
B - Array Cancellation
考虑每当出现需要 -1 +1 的免费操作,实际上就是前缀和,出现需要 +1 -1 的情况:实际上是前缀和最小的情况。
#include<bits/stdc++.h> using namespace std; const int N=1e5+500; typedef long long ll; // int a[N]; int main(){ int t;cin>>t; while(t--){ int n;cin>>n; ll sum=0,ans=1e18; for(int i=1;i<=n;i++){ // cout<<"test :"; ll x; scanf("%lld",&x),sum+=x,ans=min(ans,sum); } // cout<<"ans : "; cout<<-ans<<endl; } // system("pause"); return 0; }
A - Array Destruction
每次操作完后剩余的最大的数一定要被下一次用到,枚举开始的点,复杂度O( n ^ 2)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=4e3+500; const int maxm=1e6+500; ll a[N]; // vector<int>G[N]; vector<int>vec[maxm]; vector<pair<ll,ll> >path,curpath; int n; // bool vis[N]; ll cnt[maxm]; int check(int x,int y){ curpath.clear(); vector<int>vec; vec.push_back(a[x]);vec.push_back(a[y]); curpath.push_back(make_pair(a[x],a[y])); int pos=n-1; int tmp; if(a[x]>a[y])tmp=a[x]; else tmp=a[y]; cnt[a[x]]--;cnt[a[y]]--; while(1){ // cnt[a[x]]--;cnt[a[y]]--; // cnt[tmp]--; while(pos>0&&cnt[a[pos]]==0)pos--; if(pos==0)break; if(cnt[ tmp-a[pos] ]==0){ for(int i=0;i<vec.size();i++)cnt[ vec[i] ]++; return false; } curpath.push_back(make_pair(a[pos],tmp-a[pos])); vec.push_back(a[pos]);vec.push_back(tmp-a[pos]); cnt[a[pos]]--;cnt[tmp-a[pos]]--; tmp=a[pos]; } return true; } int main(){ int t;cin>>t; while(t--){ path.clear(); cin>>n; n*=2; memset(cnt,0,sizeof cnt); for(int i=1;i<=n;i++)scanf("%lld",&a[i]),cnt[a[i]]++; sort(a+1,a+1+n); // for(int i=1;i<=n;i++){ // for(int j=i+1;j<=n;j++){ // ll tmp=a[i]+a[j]; // if(vec[ tmp ].empty())continue; // for(int k=0;k<vec[tmp].size();k++){ // G[ vec[tmp][k] ].push_back(j); // G[ vec[tmp][k] ].push_back(i); // } // } // } bool flag=0; int ans=-1; for(int i=1;i<n;i++){ if(check(i,n)){ flag=1; ans=a[i]+a[n]; path=curpath; break; } } if(!flag)puts("NO"); else { puts("YES"); cout<<ans<<endl; for(int i=0;i<path.size();i++){ // cout<<"test : "; printf("%lld %lld\n",path[i].first,path[i].second); } } // for(int i=1;i<=n;i++)cnt[a[i]]--; } // system("pause"); return 0; }
B - 13th Labour of Heracles
当k变大,实际上会把点权最大的贡献+1,
#include<bits/stdc++.h> using namespace std; #define mkp make_pair const int N=1e5+500; typedef long long ll; // ll x[N],y[N]; // map<pair<ll,ll>,ll>mp; ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} ll w[N],deg[N]; vector<ll>vec; int main(){ // cout<<gcd(0,0)<<endl; int t;cin>>t; while(t--){ vec.clear(); int n;cin>>n; ll ans=0; for(int i=1;i<=n;i++)deg[i]=0,scanf("%lld",&w[i]),ans+=w[i]; for(int i=1;i<n;i++){ int u,v;scanf("%d %d",&u,&v); deg[u]++;deg[v]++; } for(int i=1;i<=n;i++){ for(int j=1;j<deg[i];j++){ vec.push_back(w[i]); } } sort(vec.begin(),vec.end(),greater<ll>()); // cout<<"test : "; cout<<ans<<" "; for(int i=0;i<vec.size();i++){ ans+=vec[i]; printf("%lld ",ans); } puts(""); } // system("pause"); return 0; }
E - Full Turn
如果两个人的视线相遇,就是两个向量的夹角180度,把每个向量标准化以后,直接统计map。
#include<bits/stdc++.h> using namespace std; #define mkp make_pair const int N=1e5+500; typedef long long ll; ll x[N],y[N]; map<pair<ll,ll>,ll>mp; ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} int main(){ // cout<<gcd(0,0)<<endl; int t;cin>>t; while(t--){ mp.clear(); int n;cin>>n; for(int i=1;i<=n;i++){ ll x1,y1,x2,y2; scanf("%lld %lld %lld %lld",&x1,&y1,&x2,&y2); x[i]=x2-x1;y[i]=y2-y1; if(x[i]==0&&y[i]==0); else if(x[i]==0&&y[i]!=0){ y[i]=y[i]/abs(y[i]); } else if(y[i]==0&&x[i]!=0){ x[i]/=abs(x[i]); } else { ll g=gcd(x[i],y[i]); g=abs(g); x[i]/=g;y[i]/=g; } mp[mkp(x[i],y[i])]++; } // for(int i=1;i<=n;i++){ // cout<<"test : "; // cout<<x[i]<<" "<<y[i]<<endl; // } ll ans=0; for(int i=1;i<=n;i++){ if(mp[mkp(-x[i],-y[i])])ans+=mp[mkp(-x[i],-y[i])]; } // cout<<"ans : "; cout<<ans/2<<endl; } // system("pause"); return 0; }
想的太多,做的太少;