A. Gabriel and Caterpillar
模拟,注意爆int。
#include <bits/stdc++.h>
using namespace std;
int main(){
ll h1,h2;
ll a,b;
cin>>h1>>h2>>a>>b;
h1+=8*a;
if(h1>=h2){
cout<<0<<endl;
}else{
h1-=12*b;
bool ok=0;
for(int i=1;i<=200000;i++){
h1+=12*a;
if(h1>=h2){
cout<<i<<endl;
ok=1;
break;
}
h1-=12*b;
}
if(!ok){
cout<<-1<<endl;
}
}
return 0;
}
B. z-sort
排序以后,贪心从中间往两边取,一定有解的。
#include <bits/stdc++.h>
using namespace std;
int a[1111];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+n+1);
int mid = (n+1)>>1;
int l = mid+1;
int r = mid;
for(int i=1;i<=n;i++){
if(i&1){
l--;
cout<<a[l]<<" ";
}else{
r++;
cout<<a[r]<<" ";
}
}
return 0;
}
C. Foe Pairs
先把排列弄成升序,然后按左端点降序处理。逆序枚举区间起点,以此为起点的区间的终点不能“跃过”出现过的任何pair。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int a[300010];
int mp[300010];
pair<int,int> ps[300010];
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
mp[a[i]] = i;
}
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
ps[i].first = mp[u];
ps[i].second = mp[v];
if(ps[i].first>ps[i].second){
swap(ps[i].first,ps[i].second);
}
}
sort(ps+1,ps+m+1);
ll ans = 0;
int k=m;
int MIN = n+1;
for(int i=n;i>0;i--){
while(ps[k].first>=i && k){
MIN = min(MIN,ps[k].second);
k--;
}
ll tmp = MIN-i;
ans += tmp;
}
cout<<ans<<endl;
return 0;
}
D. Nested Segments
又一个区间问题。离散化,按区间右端点升序枚举,树状数组维护区间左端点的位置。每枚举到一个区间,根据当前左端点,在BIT中查询当前区间包含了多少区间,把区间左端点加入BIT。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 200010;
struct node{
int l,r;
int id;
node(){
}
node(int l,int r):l(l),r(r){
}
bool operator<(const node& other)const{
return r<other.r;
}
}nds[maxn];
int b[maxn<<1];
int k;
int Find(int x){
return lower_bound(b,b+k,x)-b+1;
}
int c[maxn<<1];
int ans[maxn];
inline int lowbit(int x){
return x&(-x);
}
void update(int x){
while(x<=400010){
c[x]++;
x+=lowbit(x);
}
}
int query(int x){
int ans = 0;
while(x){
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
scanf("%d%d",&nds[i].l,&nds[i].r);
nds[i].id = i;
b[i<<1] = nds[i].l;
b[(i<<1)+1] = nds[i].r;
}
k = n<<1;
sort(b,b+k);
k = unique(b,b+k) - b;
for(int i=0;i<n;i++){
nds[i].l = Find(nds[i].l);
nds[i].r = Find(nds[i].r);
}
sort(nds,nds+n);
int tot = 0;
for(int i=0;i<n;i++){
int q = query(nds[i].l);
ans[nds[i].id] = tot-q;
update(nds[i].l);
tot++;
}
for(int i=0;i<n;i++){
printf("%d\n",ans[i]);
}
return 0;
}
E. Pursuit For Artifacts
因为走过的边不能再走,考虑双连通缩点,在同一个连通分量里的点肯定是可以绕完一圈的。缩点以后建立新图,相同连通分量内的边,如果上面有神器,就为这个分量做一个标记,可以认为只要路径能经过这个分量,就能拿到神器。不同连通分量之间的边,按原图建,注意不要删边。最后我们可以从起点的连通分量dfs到终点,如果路上经过有神器的连通分量或有神器的边,则输出YES。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 300010;
bool vis[maxn];
int dfn[maxn];
int low[maxn];
struct Edge{
int v;
int w;
Edge(int v,int w):v(v),w(w){
}
Edge(){
}
}edges[maxn<<1],newedges[maxn<<1];
vector<int> oriG[maxn];
vector<int> G[maxn];
int dfs_clock = 0;
stack<int> sta;
int a,b;
int belong[maxn];
int hasArt[maxn];
bool instack[maxn];
void tarjan(int u,int p){
dfn[u]=low[u]=++dfs_clock;
sta.push(u);
instack[u]=1;
int sz=oriG[u].size();
for(int i=0;i<sz;i++){
int v= edges[oriG[u][i]].v;
if(v==p)continue;
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
}else if(instack[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
while(1){
int t=sta.top(); sta.pop(); instack[t]=0;
belong[t]=u;
if(t==u)break;
}
}
}
int u[maxn];
int v[maxn];
int w[maxn];
bool ok = 0;
bool dfs(int u,int p){
if(u==belong[b]){
if(hasArt[u])ok=1;
return 1;
}
int sz=G[u].size();
bool findB = 0;
for(int i=0;i<sz;i++){
int v = newedges[G[u][i]].v;
if(v==p)continue;
if(dfs(v,u)){
findB = 1;
if(newedges[G[u][i]].w){
ok = 1;
}
}
}
if(findB && hasArt[u]){
ok = 1;
}
return findB;
}
int main(){
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++){
scanf("%d%d%d",&u[i],&v[i],&w[i]);
edges[i<<1] = Edge(v[i],w[i]);
oriG[u[i]].push_back(i<<1);
edges[(i<<1)|1] = Edge(u[i],w[i]);
oriG[v[i]].push_back((i<<1)|1);
}
cin>>a>>b;
tarjan(a,-1);
int k=0;
for(int i=0;i<m;i++){
int uu = belong[u[i]];
int vv = belong[v[i]];
if(uu==vv){
if(w[i]){
hasArt[uu] = 1;
}
}else{
newedges[k] = Edge(vv,w[i]);
G[uu].push_back(k++);
newedges[k] = Edge(uu,w[i]);
G[vv].push_back(k++);
}
}
dfs(belong[a],-1);
if(ok){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
return 0;
}