2021.12.19 eleveni的刷题记录

0. 本次记录有意思的题

0.1 每个点恰好经过一次并且求最小时间

P2469 [SDOI2010]星际竞速

https://www.luogu.com.cn/problem/P2469

费用流

0.2 把数字序列转化为01串

AT2165 [AGC006D] Median Pyramid Hard

https://www.luogu.com.cn/problem/AT2165

二分

1. 基础算法

1.1 二分

https://www.luogu.com.cn/problem/AT2165

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; const int N=2e5+10;
int n,a[N]; inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline bool check(int maxn){
for(int i=0;i<n-1;i++){
if((a[n-i]<=maxn&&a[n-i-1]<=maxn)||(a[n+i]<=maxn&&a[n+i+1]<=maxn))return true;
if((a[n-i]>maxn&&a[n-i-1]>maxn)||(a[n+i]>maxn&&a[n+i+1]>maxn))return false;
}
return a[1]<=maxn;
} signed main(){
IOS;
cin>>n;
for(int i=1;i<=n*2-1;i++)cin>>a[i];
int L=1,R=n*2-1,mid,ans;
while(L<R){
mid=(L+R)>>1;
if(check(mid))R=ans=mid;
else L=mid+1;
}
cout<<ans;
return 0;
}

https://www.luogu.com.cn/problem/P4343

记得把右边界开大!!!!

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define ls (x)<<1
#define rs (x)<<1|1
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; #define int long long
const int N=1e5+10;
int n,m,num[N]; inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline bool check1(int maxn){
int now=0,cnt=0;
for(int i=1;i<=n;i++){
now+=num[i];
if(now<0)now=0;
if(now>=maxn)++cnt,now=0;
}
return cnt>=m;
}
inline bool check2(int maxn){
int now=0,cnt=0;
for(int i=1;i<=n;i++){
now+=num[i];
if(now<0)now=0;
if(now>=maxn)++cnt,now=0;
}
return cnt<=m;
} signed main(){
n=read();m=read();
int maxn=-1,minn=0x3f3f3f3f,R1=-1,R2=-1,L1=0,L2=0;
int tot=0;
for(int i=1;i<=n;i++){
num[i]=read();
tot+=num[i];
R1=max(R1,tot);R2=R1;
}
R1=R2=1e14;;
while(L1<=R1){
int mid=(L1+R1)>>1;
//cout<<L1<<" "<<R1<<" "<<mid<<endl;
if(check1(mid))maxn=mid,L1=mid+1;
else R1=mid-1;
}
//if(maxn==-1)return puts("-1"),0;
while(L2<=R2){
int mid=(L2+R2)>>1;
if(check2(mid))minn=mid,R2=mid-1;
else L2=mid+1;
}
//if(minn==0x3f3f3f3f)return puts("-1"),0;
if(maxn<minn)return puts("-1"),0;
cout<<max(minn,1*1ll)<<" "<<maxn;
return 0;
}

1.2 贪心

https://www.luogu.com.cn/problem/P4107

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define ls (x)<<1
#define rs (x)<<1|1
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; #define int long long
const int N=2e6+10;
int n,m,cnt,head[N],tmp[N],ans,val[N];
struct node{
int to,next;
}a[N]; inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline void add(int u,int v){
++cnt;
a[cnt].to=v;
a[cnt].next=head[u];
head[u]=cnt;
}
inline int cmp(int x,int y){
return x<y;
}
inline void dfs(int x){
for(int i=head[x];i;i=a[i].next){
int v=a[i].to;
dfs(v);
}
int top=0;
for(int i=head[x];i;i=a[i].next){
int v=a[i].to;
tmp[++top]=val[v];
}
sort(tmp+1,tmp+top+1,cmp);
for(int i=1;i<=top;i++){
if(val[x]+tmp[i]-1<=m)val[x]+=tmp[i]-1,++ans;
else break;
}
} signed main(){
n=read();m=read();
for(int i=1;i<=n;i++)val[i]=read();
for(int i=1;i<=n;i++){
int tot=read();
val[i]+=tot;
for(int j=1;j<=tot;j++){
int x=read()+1;
add(i,x);
}
}
dfs(1);
cout<<ans;
return 0;
}

2. 计算几何

2.1 半平面交

如果不知道输入顺序,那么就顺时针逆时针都跑一遍求最大值

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std; const int N=1e5+10;
const double eps=1e-13;//!
int L,R; struct node{
double x,y;
inline node operator +(const node &b)const{
return (node){x+b.x,y+b.y};
}
inline node operator -(const node &b)const{
return (node){x-b.x,y-b.y};
}
}stain[N],Cross[N];
inline node operator *(node a,double k){
return (node){a.x*k,a.y*k};
}
inline node operator /(node a,double k){
return (node){a.x/k,a.y/k};
}
inline double cross(node x,node y){
return x.x*y.y-x.y*y.x;
}
inline double dot(node x,node y){
return x.x*y.x+x.y*y.y;
} struct nodei{
node pos,vec;
double angle;
inline void add(node a,node b){//
pos=a;vec=b;
angle=atan2(b.y,b.x);
}
bool operator <(const nodei &b){
return angle<b.angle;
}
}a[N],q[N];
inline int judge(nodei x,node y){
return cross(x.vec,y-x.pos)<=-eps;//判断点y是否在直线x右边
}
inline node findCross(nodei x,nodei y){
node z=x.pos-y.pos;
double t=cross(y.vec,z)/cross(x.vec,y.vec);
return x.pos+x.vec*t;
}
inline double calcArea(int n,node *a){// a:Cross ,求多边形面积
double fin=0.0;
for(int i=1;i<n;i++)fin+=cross(a[i],a[i+1]);
fin+=cross(a[n],a[1]);
fin/=2.0;
return fin;
}
inline int halfPlane(int n){
sort(a+1,a+n+1);
L=R=0;
q[0]=a[1];
for(int i=2;i<=n;i++){
while(L<R&&judge(a[i],Cross[R]))--R;
while(L<R&&judge(a[i],Cross[L+1]))++L;
q[++R]=a[i];
if(fabs(cross(q[R].vec,q[R-1].vec))<=eps){//第R条直线与第R-1条直线平行
if(judge(q[R],q[R-1].pos)&&dot(q[R].vec,q[R-1].vec)<=-eps)return 0;
--R;
if(!judge(q[R],a[i].pos))q[R]=a[i];//在左边
}
if(L<R)Cross[R]=findCross(q[R],q[R-1]);
}
while(L<R&&judge(q[L],Cross[R]))--R;
//cout<<"Case 2"<<endl;
if(R-L<=1)return 0;//左开右闭区间,当R-L<=1时就只有一条直线
Cross[L]=findCross(q[L],q[R]);
//cout<<"Case 1"<<endl;//
return 1;
} int main(){
int t,top=0;
//cin>>t;
//while(t--){
int n;cin>>n;
for(int i=n;i>=1;i--)cin>>stain[i].x>>stain[i].y;
for(int i=1;i<n;i++)a[++top].add(stain[i],stain[i%n+1]-stain[i]);
a[++top].add(stain[n],stain[1]-stain[n]);
//}
double maxn=0.0;
if(halfPlane(top))maxn=max(maxn,calcArea(R-L+1,Cross+L-1));
top=0;
for(int i=1;i<=n/2;i++)swap(stain[i],stain[n-i+1]);
for(int i=1;i<n;i++)a[++top].add(stain[i],stain[i+1]-stain[i]);
a[++top].add(stain[n],stain[1]-stain[n]);
if(halfPlane(top))maxn=max(maxn,calcArea(R-L+1,Cross+L-1));
printf("%.2lf",maxn);
return 0;
}

3. 图论

3.1 找规律

https://www.luogu.com.cn/problem/P2407

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; const int N=810;
int n,m,C[N][N],R[N][N];
char a[N][N]; int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%s",a[i]+1);
int aim=0;
for(int j=1;j<=m;j++){
if(a[i][j]=='T')aim^=1;
R[i][j]=aim;
}
}
for(int j=1;j<=m;j++){
int aim=0;
for(int i=1;i<=n;i++){
if(a[i][j]=='T')aim^=1;
C[i][j]=aim;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)putchar('o'),putchar(R[i][j]?45:32);
cout<<endl;
if(i==n)break;
for(int j=1;j<=m;j++)putchar(C[i][j]?124:32),putchar(32);
cout<<endl;
}
return 0;
}

3.2 最短路

https://www.luogu.com.cn/problem/P4162

SLF优化SPFA

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cmath>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; const int N=35;
const int M=910;
const int inf=0x3f3f3f3f;
int n,m,T,cnt,head[M],start[M],vis[M],cnti[M],dis[M];
double ans,DIS[M][M];
char mapi[N][N];
struct node{
int to,next,val;
}a[M*8]; inline void add(int u,int v,int w){
++cnt;
a[cnt].to=v;
a[cnt].next=head[u];
a[cnt].val=w;
head[u]=cnt;
}
inline int id(int x,int y){
return (x-1)*m+y;
}
inline void spfa(int s){
deque<int>q;
for(int i=1;i<=n*m;i++)dis[i]=inf,vis[i]=0;
if(start[s])dis[s]=1;else dis[s]=0;
vis[s]=1;
q.push_back(s);
while(!q.empty()){
int x=q.front();q.pop_front();
if(dis[x]<=T)ans=max(ans,DIS[s][x]);
vis[x]=0;
for(int i=head[x];i;i=a[i].next){
int v=a[i].to;
if(dis[v]>dis[x]+a[i].val){
dis[v]=dis[x]+a[i].val;
if(!vis[v]){
vis[v]=1;
if(dis[v]<dis[q.front()])q.push_front(v);
else q.push_back(v);
}
}
}
}
//cout<<"start "<<s<<endl;
//for(int i=1;i<=n*m;i++)cout<<dis[i]<<" ";cout<<endl;
} int main(){
cin>>n>>m>>T;
for(int i=1;i<=n;i++){
scanf("%s",mapi[i]+1);
for(int j=1;j<=m;j++){
int x=id(i,j);
if(mapi[i][j]=='1')start[x]=1;
}
}
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
for(int k=1;k<=n;k++)for(int l=1;l<=m;l++){
int id1=id(i,j),id2=id(k,l);
DIS[id1][id2]=DIS[id2][id1]=(double)sqrt((double)(i-k)*(i-k)+double(j-l)*(j-l));
}
/*cout<<"DIS "<<endl;
for(int i=1;i<=n*m;i++){
for(int j=1;j<=n*m;j++)cout<<DIS[i][j]<<" ";
cout<<endl;
}
cout<<endl;*/
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
int idi=id(i,j);
if(i<n)add(idi,idi+m,start[idi+m]),add(idi+m,idi,start[idi]);
if(j<m)add(idi,idi+1,start[idi+1]),add(idi+1,idi,start[idi]);
}
for(int i=1;i<=n*m;i++)spfa(i);
printf("%.6lf",ans);
return 0;
}

3.3 Tarjan

https://www.luogu.com.cn/problem/P2469

60pts:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<cmath>
#define ls (x)<<1
#define rs (x)<<1|1
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; const int N=4e4+10;
const int M=2e5+10;
const int K=6e4+10;
int n,m,cnt,head[N],cnti,headi[N],ans;
int ind,dfn[N],low[N],belong[N],vis[N];
int dfsx,true_id[N],id_true[N],dep[N],top[N],son[N],sizei[N],fa[N];
int val[N<<4],lazy[N<<4];
struct Query{
int op,u,v,ans;
}queryi[K];
struct node{
int to,next,flag;
}a[M],ai[M];
stack<int>s; inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline void add(int u,int v){
++cnt;
a[cnt].to=v;
a[cnt].next=head[u];
head[u]=cnt;
}
inline void addi(int u,int v){
++cnti;
ai[cnti].to=v;
ai[cnti].next=headi[u];
headi[u]=cnti;
}
inline void Tarjan(int x,int fai){
dfn[x]=low[x]=++ind;
s.push(x);
for(int i=head[x];i;i=a[i].next){
if(a[i].flag==1)continue;
int v=a[i].to;
if(!dfn[v])Tarjan(v,x),low[x]=min(low[x],low[v]);
else if(dfn[v]<dfn[x]&&v!=fai)low[x]=min(low[x],dfn[v]);
}
int k=0;
if(low[x]==dfn[x]){
do{
k=s.top();s.pop();
belong[k]=x;
vis[k]=0;
}while(k!=x);
}
}
inline void build(int x,int l,int r){
if(l==r)return (void)(val[x]=1);
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
val[x]=val[ls]+val[rs];
}
inline void pushdown(int x){
if(!lazy[x])return ;
lazy[ls]=lazy[rs]=lazy[x];
val[ls]=val[rs]=0;
lazy[x]=0;
}
inline void change(int x,int l,int r,int L,int R){
if(L>r||R<l)return ;
if(l>=L&&r<=R)return (void)(val[x]=0,lazy[x]=1);
pushdown(x);
int mid=(l+r)>>1;
if(L<=mid)change(ls,l,mid,L,R);
if(R>mid)change(rs,mid+1,r,L,R);
val[x]=val[ls]+val[rs];
}
inline int query(int x,int l,int r,int L,int R){
if(L>r||R<l)return 0;
if(l>=L&&r<=R)return val[x];
pushdown(x);
int mid=(l+r)>>1;
int ans=0;
if(L<=mid)ans+=query(ls,l,mid,L,R);
if(R>mid)ans+=query(rs,mid+1,r,L,R);
val[x]=val[ls]+val[rs];
return ans;
}
inline void dfs1(int x,int fai){
sizei[x]=1;fa[x]=fai;dep[x]=dep[fai]+1;
for(int i=headi[x];i;i=ai[i].next){
int v=ai[i].to;
if(v==fai)continue;
dfs1(v,x);
sizei[x]+=sizei[v];
if(sizei[v]>sizei[son[x]])son[x]=v;
}
}
inline void dfs2(int x,int topi){
top[x]=topi;
true_id[x]=++dfsx;id_true[dfsx]=x;
if(son[x]&&!true_id[son[x]])dfs2(son[x],topi);
for(int i=headi[x];i;i=ai[i].next){
int v=ai[i].to;
if(true_id[v])continue;
if(v==fa[x]||v==son[x])continue;
dfs2(v,v);
}
}
inline void changeline(int x,int y,int flag){
//cout<<x<<" "<<y<<" "<<top[x]<<" "<<top[y]<<endl;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
if(flag)ans+=query(1,1,dfsx,true_id[top[x]],true_id[x]);
else change(1,1,dfsx,true_id[top[x]],true_id[x]);
x=fa[top[x]];
//cout<<x<<" "<<y<<" "<<top[x]<<" "<<top[y]<<endl;
}
if(dep[x]>dep[y])swap(x,y);
if(flag)ans+=query(1,1,dfsx,true_id[x]+1,true_id[y]);
else change(1,1,dfsx,true_id[x]+1,true_id[y]);
//cout<<x<<" "<<y<<endl;//
}
inline void find(){
for(int i=1;i<=20;i++)cout<<val[i]<<" ";
cout<<endl;
} int main(){
n=read();m=read();
for(int i=1;i<=m;i++){
int u,v;
u=read();v=read();
add(u,v);add(v,u);
}
int tot=0;
for(int i=1;i;i++){
queryi[i].op=read();
if(queryi[i].op==-1){
tot=i-1;
break;
}
queryi[i].u=read();queryi[i].v=read();
if(queryi[i].op==0){
for(int j=head[queryi[i].u];j;j=a[j].next){
if(a[j].flag==1)continue;
int v=a[j].to;
if(v==queryi[i].v){
a[j].flag=1;
break;
}
}
for(int j=head[queryi[i].v];j;j=a[j].next){
if(a[j].flag==1)continue;
int v=a[j].to;
if(v==queryi[i].u){
a[j].flag=1;
break;
}
}
}
}
for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i,i);
/*cout<<"belong "<<endl;
for(int i=1;i<=n;i++)cout<<belong[i]<<" ";cout<<endl;
cout<<"addi "<<endl;*/
for(int i=1;i<=n;i++)
for(int j=head[i];j;j=a[j].next){
if(a[j].flag)continue;
int v=a[j].to;
if(belong[i]!=belong[v]){
int from=belong[i],to=belong[v];
addi(from,to);addi(to,from);
//cout<<from<<" "<<to<<endl;
}
}
//cout<<"start "<<ai[1].to<<endl;
dfs1(ai[1].to,ai[1].to);dfs2(ai[1].to,ai[1].to);
/*cout<<"dfsx "<<endl;
for(int i=1;i<=dfsx;i++)cout<<i<<" "<<id_true[i]<<endl;
cout<<"son "<<endl;
for(int i=1;i<=n;i++)cout<<son[i]<<" ";cout<<endl;
cout<<"top "<<endl;
for(int i=1;i<=n;i++)cout<<top[i]<<" ";cout<<endl;*/
build(1,1,dfsx);
//cout<<"queryi "<<endl;
for(int i=tot;i>=1;i--){
ans=0;
int ui=belong[queryi[i].u],vi=belong[queryi[i].v];
//cout<<queryi[i].op<<" "<<ui<<" "<<vi<<" "<<endl;
changeline(ui,vi,queryi[i].op);
queryi[i].ans=ans;
//find();
}
for(int i=1;i<=tot;i++)if(queryi[i].op==1)cout<<queryi[i].ans<<endl;
return 0;
}

别人100pts:

#include<map>
#include<stack>
#include<cstdio>
#include<algorithm>
using namespace std;
template<class type>inline const void read(type &in)
{
in=0;char ch=getchar();short fh=1;
while (ch<48||ch>57)fh=ch=='-'?-1:fh,ch=getchar();
while (ch>47&&ch<58)in=(in<<3)+(in<<1)+ch-48,ch=getchar();
in*=fh;
}
const int N=3e4+10,M=1e5+10,Q=4e4+10;
int n,m,a[M],b[M];
stack<int>ans;
map<pair<int,int>,int>e;
struct question{int u,v,type;}q[Q]; //存储每个询问信息
class Edge
{
private:
int cnt;
public:
int head[N],to[M<<1],next[M<<1];
inline const void addedge(int u,int v)
{
next[++cnt]=head[u];
head[u]=cnt;
to[cnt]=v;
}
inline const void connect(int u,int v)
{
addedge(u,v);
addedge(v,u);
}
}g,t;
class Double_Connected_Component //边双处理
{
private:
stack<int>s;
int dfn[N],low[N],cnt;
public:
int dcc[N],tot;
protected:
inline const void tarjan(int u,int fa)
{
dfn[u]=low[u]=++cnt;s.push(u);int v;
for (int i=g.head[u];i;i=g.next[i])
if ((v=g.to[i])!=fa)
if (!dfn[v])tarjan(v,u),low[u]=min(low[u],low[v]);
else if (!dcc[v])low[u]=min(low[u],dfn[v]);
if (low[u]!=dfn[u])return;tot++;
do v=s.top(),s.pop(),dcc[v]=tot;while (u!=v);
}
public:
inline const void tarjan()
{
for (int i=1;i<=n;i++)
if (!dfn[i])
tarjan(i,0);
}
inline const void rebuild() //缩点成树
{
for (int i=1;i<=n;i++)
for (int u,v,j=g.head[i];j;j=g.next[j])
if ((u=dcc[i])!=(v=dcc[g.to[j]]))
t.addedge(u,v);
}
}dcc;
class Segment_Tree //线段树(指针)
{
private:
struct tree
{
int sum;
bool tag;
tree *lson,*rson;
inline const void pushup()
{
sum=lson->sum+rson->sum;
}
inline const void cover()
{
tag=1;sum=0;
}
inline const void pushdown()
{
if (!tag)return;
lson->cover();
rson->cover();
tag=0;
}
inline const void update(int l,int r,int L,int R)
{
if (l>R||r<L)return;
if (l>=L&&r<=R)return cover();
pushdown();
int mid=l+r>>1;
lson->update(l,mid,L,R);
rson->update(mid+1,r,L,R);
pushup();
}
inline const int query(int l,int r,int L,int R)
{
if (l>R||r<L)return 0;
if (l>=L&&r<=R)return sum;
pushdown();
int mid=l+r>>1;
return lson->query(l,mid,L,R)+rson->query(mid+1,r,L,R);
}
}memory_pool[N<<2],*tail;
inline const void init()
{
tail=memory_pool;
}
inline tree *spawn()
{
tree *p=tail++;
p->tag=p->sum=0;
p->lson=p->rson=NULL;
return p;
}
public:
tree *root;
inline Segment_Tree(){init();}
inline const void build(tree *&p,int l,int r)
{
p=spawn();
if (l==r)return (void)(p->sum=(l!=1)); //边权转点权,1号点(根节点)上面没有边,权值为0
int mid=l+r>>1;
build(p->lson,l,mid);
build(p->rson,mid+1,r);
p->pushup();
}
}sgt;
class Heavy_Light_Decomposition //树剖
{
private:
int size[N],top[N],fa[N],dep[N],dfn[N],wson[N],cnt;
public:
inline const void dfs(int p)
{
size[p]=1;
for (int i=t.head[p];i;i=t.next[i])
{
int son=t.to[i];
if (son==fa[p])continue;
fa[son]=p;dep[son]=dep[p]+1;
dfs(son);size[p]+=size[son];
if (size[son]>size[wson[p]])wson[p]=son;
}
}
inline const void dfs(int p,int tp)
{
top[p]=tp;dfn[p]=++cnt;
if (wson[p])dfs(wson[p],tp);
for (int son,i=t.head[p];i;i=t.next[i])
if (!dfn[son=t.to[i]])
dfs(son,son);
}
inline const void update(int a,int b)
{
while (top[a]^top[b])
{
if (dep[top[a]]<dep[top[b]])swap(a,b);
sgt.root->update(1,dcc.tot,dfn[top[a]],dfn[a]);
a=fa[top[a]];
}
if (dep[a]>dep[b])swap(a,b);
sgt.root->update(1,dcc.tot,dfn[a]+1,dfn[b]);
}
inline const int query(int a,int b)
{
int ans=0;
while (top[a]^top[b])
{
if (dep[top[a]]<dep[top[b]])swap(a,b);
ans+=sgt.root->query(1,dcc.tot,dfn[top[a]],dfn[a]);
a=fa[top[a]];
}
if (dep[a]>dep[b])swap(a,b);
return ans+sgt.root->query(1,dcc.tot,dfn[a]+1,dfn[b]);
}
}hld;
int main()
{
read(n);read(m);
for (int i=1;i<=m;i++)read(a[i]),read(b[i]);
int qtot;
for (qtot=1;read(q[qtot].type),~q[qtot].type;qtot++)
{
read(q[qtot].u);read(q[qtot].v);
if (q[qtot].type)continue;
e[make_pair(q[qtot].u,q[qtot].v)]++;
e[make_pair(q[qtot].v,q[qtot].u)]++; //无向图,反过来的也要更改
}
for (int i=1;i<=m;i++)
if (e.find(make_pair(a[i],b[i]))!=e.end()&&e[make_pair(a[i],b[i])])
e[make_pair(a[i],b[i])]--,e[make_pair(b[i],a[i])]--;
else g.connect(a[i],b[i]);
dcc.tarjan();dcc.rebuild();
hld.dfs(1);hld.dfs(1,1);
sgt.build(sgt.root,1,dcc.tot);
for (int i=qtot-1;i;i--)
if (q[i].type)ans.push(hld.query(dcc.dcc[q[i].u],dcc.dcc[q[i].v])); //由于是倒序处理,所以输出也要倒过来,因为tarjan缩点的时候会用到栈,干脆也用栈来实现倒序好了
else hld.update(dcc.dcc[q[i].u],dcc.dcc[q[i].v]);
while (ans.size())printf("%d\n",ans.top()),ans.pop();
return 0;
}

3.4 网络流

3.4.1 费用流

https://www.luogu.com.cn/problem/P2469

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define ls (x)<<1
#define rs (x)<<1|1
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; const int N=160010;
const int inf=0x3f3f3f3f;
int n,m,start,endi,cnt=1,head[N];
int maxnflow,maxncost,vis[N],flow[N],pre[N],dis[N];
struct node{
int to,next,val,cost;
}a[N*3]; inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline void addi(int u,int v,int w,int x){
++cnt;
a[cnt].to=v;
a[cnt].val=w;
a[cnt].cost=x;
a[cnt].next=head[u];
head[u]=cnt;
}
inline void add(int u,int v,int w,int x){
addi(u,v,w,x);addi(v,u,0,-x);
}
inline int spfa(int s,int t){
memset(dis,inf,sizeof(dis));
memset(vis,0,sizeof(vis));
queue<int>q;
dis[s]=0;flow[s]=inf;vis[s]=1;
q.push(s);
while(!q.empty()){
int x=q.front();q.pop();
vis[x]=0;
for(int i=head[x];i;i=a[i].next){
int v=a[i].to;
if(dis[v]>dis[x]+a[i].cost&&a[i].val){
dis[v]=dis[x]+a[i].cost;
flow[v]=min(flow[x],a[i].val);
pre[v]=i;
if(!vis[x])vis[v]=1,q.push(v);
}
}
}
return dis[t]!=inf;
}
inline void update(int s,int t){
int x=t;
while(x!=s){
int xi=pre[x];
a[xi].val-=flow[t];
a[xi^1].val+=flow[t];
x=a[xi^1].to;
}
maxnflow+=flow[t];
maxncost+=flow[t]*dis[t];
}
inline void EK(int s,int t){
while(spfa(s,t))update(s,t);
} int main(){
n=read();m=read();
start=n*2+1,endi=n*2+2;
for(int i=1;i<=n;i++){
int x=read();
add(start,i,1,0);
add(start,i+n,1,x);
add(i+n,endi,1,0);
}
for(int i=1;i<=m;i++){
int u,v,w;
u=read();v=read();w=read();
if(u>v)swap(u,v);
add(u,v+n,1,w);
}
EK(start,endi);
cout<<maxncost;
return 0;
}

4. 数学

4.1 矩阵加速

https://www.luogu.com.cn/problem/P2461

呵呵,输出必须是非负整数!!

20pts:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define ls (x)<<1
#define rs (x)<<1|1
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; #define int long long
const int N=20;
int n,m,K,mod;
struct Matrix{
int num[N][N];
Matrix(){
memset(num,0,sizeof(num));
}
inline Matrix operator *(const Matrix &b)const{
Matrix c;
for(int i=1;i<=K;i++)
for(int j=1;j<=K;j++)
for(int k=1;k<=K;k++)
c.num[i][j]=(c.num[i][j]+num[i][k]*b.num[k][j]%mod)%mod;
return c;
}
}ans,basic; inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline Matrix operator ^(Matrix x,int y){
Matrix fin=x;--y;
while(y){
if(y&1)fin=fin*x;
x=x*x;
y>>=1;
}
return fin;
} signed main(){
K=read();
for(int i=1;i<=K;i++)ans.num[i][1]=read();
for(int i=K;i>=1;i--){
if(i<K)basic.num[i][i+1]=1;
basic.num[K][i]=read();
}
//for(int i=1;i<=K;i++)cout<<basic.num[K][i]<<" ";cout<<endl;
/*cout<<"ans "<<endl;
for(int i=1;i<=K;i++)cout<<ans.num[i][1]<<endl;
cout<<"basic "<<endl;
for(int i=1;i<=K;i++){
for(int j=1;j<=K;j++)cout<<basic.num[i][j]<<" ";
cout<<endl;
}
cout<<endl;*/
m=read();n=read();mod=read();
if(m-K>0)ans=(basic^(m-K))*ans;
//cout<<"ans "<<endl;
//for(int i=1;i<=K;i++)cout<<ans.num[i][1]<<endl;
int tot=ans.num[K][1];
for(int i=1;i<=(n-m)%K;i++)ans=basic*ans,tot=(tot+ans.num[K][1])%mod;
basic=basic^K;
for(int i=1;i<=(n-m)/K;i++){
ans=basic*ans;
for(int j=1;j<=K;j++)tot=(tot+ans.num[j][1])%mod;
}
cout<<tot;
return 0;
}

100pts:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define ls (x)<<1
#define rs (x)<<1|1
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; #define int long long
const int N=20;
int n,m,K,mod,sum[N];
struct Matrix{
int num[N][N];
Matrix(){
memset(num,0,sizeof(num));
}
inline Matrix operator *(const Matrix &b)const{
Matrix c;
for(int i=1;i<=K+1;i++)
for(int j=1;j<=K+1;j++)
for(int k=1;k<=K+1;k++)
c.num[i][j]=(c.num[i][j]+num[i][k]*b.num[k][j]%mod)%mod;
return c;
}
}ans,basic; inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline Matrix operator ^(Matrix x,int y){
Matrix fin;
if(y==0)return fin;
fin=x;--y;
while(y>0){
if(y&1)fin=fin*x;
x=x*x;
y>>=1;
}
return fin;
} signed main(){
K=read();
for(int i=1;i<=K;i++)ans.num[i][1]=read();
for(int i=K;i>=1;i--){
if(i<K)basic.num[i][i+1]=1;
basic.num[K+1][i]=basic.num[K][i]=read();
}
basic.num[K+1][K+1]=1;
m=read();n=read();mod=read();
for(int i=1;i<=K;i++)
sum[i]=(sum[i-1]+(ans.num[i][1]%=mod))%mod,
basic.num[K][i]%=mod,basic.num[K+1][i]%=mod;
ans.num[K+1][1]=sum[K];
int tot1=0,tot2=0;
if(m<=K+1)tot1=sum[m-1];
else tot1=((basic^(m-1-K))*ans).num[K+1][1];
if(n<=K)tot2=sum[n];
else tot2=((basic^(n-K))*ans).num[K+1][1];
//cout<<tot1<<" "<<tot2<<endl;
cout<<((tot2-tot1)%mod+mod)%mod;
return 0;
}

5. 动态规划

5.1 贪心优化

https://www.luogu.com.cn/problem/P2577

这个看似可以记忆化搜索。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define ls (x)<<1
#define rs (x)<<1|1
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; const int N=210;
const int inf=0x3f3f3f3f;
int n,f[N][N*N],sum[N];
struct node{
int wait,eat;
bool operator <(const node &b)const{
return eat>b.eat;
}
}a[N]; inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
} int main(){
n=read();
for(int i=1;i<=n;i++)a[i].wait=read(),a[i].eat=read();
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i].wait;
memset(f,inf,sizeof(f));
f[0][0]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=sum[i];j++){
if(j>=a[i].wait)f[i][j]=min(f[i][j],max(f[i-1][j-a[i].wait],j+a[i].eat));
f[i][j]=min(f[i][j],max(f[i-1][j],sum[i]-j+a[i].eat));
}
int ans=inf;
for(int i=0;i<=sum[n];i++)ans=min(ans,f[n][i]);
cout<<ans;
return 0;
}

最新文章

  1. 发布APP到app store
  2. Java如何保存含有时间的日期到Oracle数据库
  3. jQuery校验validate详解(转)
  4. Jquery的tmpl
  5. redis补充和rabbitmq讲解
  6. 跨容器Hybrid离线组件方案
  7. leetcode[55] Merge Intervals
  8. WDA 程序文本翻译OTR
  9. 201521123037 《Java程序设计》第13周学习总结
  10. node 使用koa2 异步读文件
  11. 前端技术之_CSS详解第五天
  12. PYTHON定义函数制作简单登录程序(详细)
  13. ReentrantReadWriteLock 读写锁解析
  14. layui layer select 选择被遮挡
  15. PTA寒假一
  16. Scoop Windows 的命令行安装程序管理工具
  17. linux 卸载自带apache httpd 安装apache httpd
  18. python 读写、创建 文件的方法(必看)
  19. 使用find命令按条件查找多个文件并且拷贝至指定目录
  20. Codeforces Round #429 (Div. 2)

热门文章

  1. ansible 五 playbooks剧本使用
  2. Python安装wxPython和ubuntu使用apt提示不能更新
  3. Rust-Sqlx极简教程
  4. 分布式锁redis
  5. 什么是 Swagger?你用 Spring Boot 实现了它吗?
  6. 如何在Ubuntu 18.04 LTS上安装和配置MongoDB
  7. 惯性传感器(IMU)
  8. C# Tutorial for Frontend Developer
  9. 在原生CSS中使用变量
  10. python-爬楼梯