比赛入口
有字典序的拓扑排序,但是因为容易超时所以可以将字符串映射成数字来操作,还有就是接收字符串后要排序后映射,不然也会超时(我也不知道这是什么玄学)
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll ;
using namespace std ;
const int N = 3e4+10 ;
const ll mod=1e9+7 ;
string str[N] ;
vector<int> v[N] ;
map<string,int> p ;
int in[N] ,ans[N],n,m,pos;
void tuopu(){
priority_queue<int,vector<int>,greater<int> > q ;
for(int i=1 ; i<=n ; ++i)
if(in[i]==0) q.push(i) ;
int cnt=0 ;
while(!q.empty()){
int x=q.top() ; q.pop() ;
ans[pos++]=x ; ++cnt ;
for(int i=0 ; i<v[x].size() ; ++i){
int y=v[x][i] ; -- in[y] ;
if(in[y]==0) q.push(y) ;
}
}
if(cnt==n){
for(int i=0 ; i<pos ; ++i) cout<<str[ans[i]]<<endl ;
}
else cout<<"Impossible"<<endl ;
}
int main(){
ios::sync_with_stdio(false);
int t; cin>>t ;
for(int cnt=1 ; cnt<=t ; ++cnt){
cin>>n>>m;
pos=0 ;
p.erase(p.begin(),p.end()) ;
for(int i=1 ; i<=n ; ++i) cin>>str[i] ;
sort(str+1,str+1+n) ; //要先排序,不然会超时(不知道这是什么玄学)
for(int i=1 ; i<=n ; ++i){
v[i].clear() ;
in[i]=0 , p[str[i]]=i ;
}
for(int i=0 ; i<m ;++i){
string a,b; cin>>a>>b ;
++in[p[b]] ;
v[p[a]].push_back(p[b]) ;
}
cout<<"Case #"<<cnt<<":"<<endl ;
tuopu();
}
return 0 ;
}
根据题意模拟一下,虽然是模拟题但是细节还是要注意一下。
#include
#include
#include
#include
#include
#include
#include
typedef long long ll ;
using namespace std ;
const int N = 1e2+10 ;
const ll mod=1e9+7 ;
int a[N] ;
int main(){
int t ; scanf("%d",&t) ;
/*4 5 1
1 1 2 4*/
while(t--){
int n,m,k; scanf("%d%d%d",&n,&m,&k) ;
for(int i=1 ; i<=n ; ++i) scanf("%d",&a[i]) ;
int cnt=0 , res=m ;
for(int i=1 ; i<=n ; ++i){
if(res-a[i]>=0) res-=a[i] ;
else{
a[i]-=res , res=m , ++cnt ,--i ;//没有收完所以要--i
continue ;
}
if(i!=n){
if(res>=k) res-=k ; //上楼
else res=m ,++cnt ; //不上楼
}
}
printf ("%d\n",cnt+1) ;
}
return 0 ;
}
因为站点的数太大需要离散一下,然后用差分标记每个站坐的人,最后差分数组最大值就是需要安排座位的数目,unique后就是站点数
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll ;
using namespace std ;
const int N = 1e5+10 ;
const ll mod=1e9+7 ;
int a[N],b[N],c[2*N] ;
vector<int> v ;
int main(){
int t; scanf("%d",&t) ;
while(t--){
v.clear() ;
int n; scanf("%d",&n) ;
for(int i=1 ; i<=n ; ++i){
scanf("%d%d",&a[i],&b[i]) ;
v.push_back(a[i]) ;
v.push_back(b[i]) ;
}
sort(v.begin(),v.end()) ;
int k = unique(v.begin(),v.end())-v.begin();
int cnt =0 ;
memset(c,0,sizeof(c)) ;
for(int i=1 ; i<=n ; ++i){
a[i] = lower_bound(v.begin(),v.begin()+k,a[i])-v.begin()+1 ;
b[i] = lower_bound(v.begin(),v.begin()+k,b[i])-v.begin()+1 ;
++c[a[i]] , --c[b[i]] ;
}
for(int i=1 ; i<=k ; ++i){
c[i] += c[i-1] ;
cnt=max(cnt,c[i]) ;
}
printf ("%d %d\n",k,cnt) ;
}
return 0 ;
}
先统计一下每个数的因子数目,然后在第二层枚举的时候,如果找到中位数就可以计算 , (a[j]+1)/2 == b[j] (因子中数刚好是当前枚举的因子)。
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll ;
using namespace std ;
const int N = 1e6+10 ;
const ll mod=1e9+7 ;
ll a[N],b[N],s[N] ;
int main(){
for(int i=1 ; i<=1e6 ; ++i){
for(int j=i ; j<=1e6 ; j+=i)
++a[j] ; //统计每个数的因子个数
}
for(int i=1 ; i<=1e6 ; ++i){
for(int j=i ; j<=1e6 ; j+=i){
++b[j] ;
//i为j的因子的中位数,中位数求平均值
if( (a[j]+1)/2 == b[j]) s[j]=(i+j/i)/2 ;
}
}
for(int i=1 ; i<=1e6 ; ++i) s[i]=(s[i]+s[i-1])%mod ;
int t; scanf("%d",&t) ;
while(t--){
ll n; scanf("%lld",&n) ;
printf ("%lld\n",s[n]) ;
}
return 0 ;
}