NO.6
J.Defend Your Country
割点+思维
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int maxn=1e6+5;
int t,n,m,cnt,a[maxn],dfn[maxn],low[maxn],sz[maxn],cut[maxn],tag[maxn];
vector<int>mp[maxn];
void tarjan(int x,int fa){
low[x]=dfn[x]=++cnt;
sz[x]=1;
int child=0;
for(auto y:mp[x]){
if(!dfn[y]){
tarjan(y,x);
sz[x]+=sz[y];
if(low[y]==dfn[x]){//子节点k无法到达x的祖先
if(fa)cut[x]=1;//割点
if(sz[y]&1)tag[x]=1;//存在“子树 ”节点数为奇
}
low[x]=min(low[x],low[y]);
if(!fa)child++;
}
else low[x]=min(low[x],dfn[y]);
}
if(child>1)cut[x]=1;//割点
}
int main(){
scanf("%d",&t);
while(t--){
ll sum=0;
cnt=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum+=a[i];
mp[i].clear();
tag[i]=cut[i]=sz[i]=dfn[i]=low[i]=0;
}
for(int i=1,x,y;i<=m;i++){
scanf("%d%d",&x,&y);
mp[x].push_back(y),mp[y].push_back(x);
}
if(!(n&1)){
printf("%lld\n",sum);
continue;
}
tarjan(1,0);
int mn=1e9;
for(int i=1;i<=n;i++){
if(!cut[i]||!tag[i])mn=min(mn,a[i]);
}
printf("%lld\n",sum-mn*2);
}
}
H.Hopping Rabbit
扫描线
#include<bits/stdc++.h>
using namespace std;
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
const int maxn=2e5+10;
int n,d;
struct node{
int l,r,t;
};
struct NODE{
int l,r,len,val;
}tree[maxn<<2];
vector<node>mp[maxn];
int mod(int x){
x%=d;
if(x<0)x+=d;
return x;
}
void add(int x1,int y1,int x2,int y2){
mp[x1].push_back({y1,y2,1});
mp[x2+1].push_back({y1,y2,-1});
}
void build(int rt,int l,int r){
tree[rt].l=l,tree[rt].r=r;
if(l==r)return;
int mid=(l+r)>>1;
build(lson);
build(rson);
}
void pushup(int rt){
if(tree[rt].val){
tree[rt].len=tree[rt].r-tree[rt].l+1;
}
else if(tree[rt].l==tree[rt].r){
tree[rt].len=0;
}
else tree[rt].len=tree[rt<<1].len+tree[rt<<1|1].len;
}
void update(int rt,int x,int y,int val){
if(x<=tree[rt].l&&tree[rt].r<=y){
tree[rt].val+=val;
pushup(rt);
return;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(x<=mid)update(rt<<1,x,y,val);
if(y>mid)update(rt<<1|1,x,y,val);
pushup(rt);
}
int query(int rt,int l,int r){
if(tree[rt].len==0){
return l;
}
int mid=(l+r)>>1;
if(tree[rt<<1].len<mid-l+1)return query(lson);
else return query(rson);
}
int main(){
scanf("%d%d",&n,&d);
for(int i=1,x1,y1,x2,y2;i<=n;i++){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x2--,y2--;
if(x2-x1+1>=d)x1=0,x2=d-1;
if(y2-y1+1>=d)y1=0,y2=d-1;
x1=mod(x1),x2=mod(x2),y1=mod(y1),y2=mod(y2);
if(x1<=x2){
if(y1<=y2){
add(x1,y1,x2,y2);
}
else add(x1,y1,x2,d-1),add(x1,0,x2,y2);
}
else{
if(y1<=y2){
add(x1,y1,d-1,y2),add(0,y1,x2,y2);
}
else{
add(x1,y1,d-1,d-1),add(0,0,x2,y2),add(0,y1,x2,d-1),add(x1,0,d-1,y2);
}
}
}
build(1,0,d-1);
for(int i=0;i<d;i++){
for(int j=0;j<mp[i].size();j++){
update(1,mp[i][j].l,mp[i][j].r,mp[i][j].t);
}
if(tree[1].len<d){
printf("YES\n%d %d\n",i,query(1,0,d-1));
return 0;
}
}
printf("NO\n");
}
F.xay loves trees
线段树+滑动窗口(双指针)
#include<bits/stdc++.h>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
const int N=4e5+5;
int t,n,siz,head,tim,ans,l[N],r[N],lazy[N<<2],mx[N<<2],st[N];
vector<int>mp1[N],mp2[N];
void pushdown(int rt){
if(lazy[rt]){
mx[rt<<1]+=lazy[rt];
mx[rt<<1|1]+=lazy[rt];
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
}
void update(int rt,int l,int r,int x,int y,int val){
if(x<=l&&r<=y){
lazy[rt]+=val;
mx[rt]+=val;
return;
}
int mid=(l+r)>>1;
pushdown(rt);
if(x<=mid)update(lson,x,y,val);
if(y>mid)update(rson,x,y,val);
mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void dfs2(int x,int fa){
l[x]=++tim;
for(auto y:mp2[x]){
if(y!=fa)dfs2(y,x);
}
r[x]=tim;
}
void dfs1(int x,int fa,int dep){
int cut=0;
st[dep]=x;
update(1,1,n,l[x],r[x],1);
if(mx[1]>1){
update(1,1,n,l[st[head]],r[st[head]],-1);
head++;
cut=1;
}
else siz++;
ans=max(ans,siz);
for(auto y:mp1[x]){
if(y!=fa)dfs1(y,x,dep+1);
}
if(cut){//借用递归消除影响
head--;
update(1,1,n,l[st[head]],r[st[head]],1);
}
else siz--;
update(1,1,n,l[x],r[x],-1);
}
void init(){
siz=tim=ans=0,head=1;
for(int i=1;i<=n;i++)mp1[i].clear(),mp2[i].clear(),l[i]=r[i]=st[i]=0;
for(int i=1;i<=4*n;i++)lazy[i]=mx[i]=0;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
init();
for(int i=1,x,y;i<n;i++){
scanf("%d%d",&x,&y);
mp1[x].push_back(y),mp1[y].push_back(x);
}
for(int i=1,x,y;i<n;i++){
scanf("%d%d",&x,&y);
mp2[x].push_back(y),mp2[y].push_back(x);
}
dfs2(1,0);
dfs1(1,0,1);
printf("%d\n",ans);
}
}
NO.7
J.xay loves Floyd
floyed思维
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int maxn=2e3+5;
const int INF=0x3f3f3f3f;
int n,m,ans,vis[maxn],d[maxn],dis[maxn][maxn],r[maxn][maxn];
vector<PII>e[maxn];
priority_queue<PII,vector<PII>,greater<PII>>p;
void dij(int now){
memset(vis,0,sizeof(vis));
memset(d,INF,sizeof(d));
p.push({0,now});
d[now]=0;
while(!p.empty()){
int x=p.top().second;
p.pop();
if(vis[x])continue;
vis[x]=1;
for(auto y:e[x]){
int a=y.first,b=y.second;
if(d[a]>d[x]+b){
d[a]=d[x]+b;
p.push({d[a],a});
}
}
}
for(int i=1;i<=n;i++)
r[now][i]=d[i];
}
int main(){
memset(dis,INF,sizeof(dis));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)dis[i][i]=0;
for(int i=1,x,y,z;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
e[x].push_back({y,z});
dis[x][y]=z;
}
for(int i=1;i<=n;i++){
dij(i);
}
for(int i=1;i<=n;i++){
if(e[i].empty())continue;
for(int j=1;j<=n;j++){
if(dis[i][j]==r[i][j]||r[i][j]==INF||i==j)continue;
for(auto x:e[i]){
int k=x.first;
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
if(dis[i][j]==r[i][j])e[i].push_back({j,dis[i][j]});
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(dis[i][j]==r[i][j])
ans++;
printf("%d\n",ans);
}