10.12 兩次考試
阿新 • • 發佈:2017-10-12
ems color clas bzoj cmp -a add clu void
上午的有些不可做...
等我成神犇之後再說吧...
下午的:
T1
原題bzoj網格
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <cmath> #include <algorithm> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int mod=20100403; constT1int N=3000006; ll qpow(ll a,int ci) { ll ans=1; while(ci) { if(ci&1) ans=ans*a%mod; a=a*a%mod; ci>>=1; } return ans; } ll jie[N],jieni[N]; void chu() { jie[0]=1; for(int i=1;i<N;++i) jie[i]=jie[i-1]*i%mod; jieni[N-1]=qpow(jie[N-1],mod-2)%mod; for(int i=N-2;i>=1;--i) jieni[i]=jieni[i+1]*(ll)(i+1)%mod; jieni[0]=1; } int n,m; inline ll C(int n,int m) { if(n<0||m<0) return 0; if(n<m) return 0; return jie[n]*jieni[m]%mod*jieni[n-m]%mod; } int main(){ chu(); scanf("%d%d",&n,&m); printf("%lld", (C(n+m,n)-C(n+m,n+1)+mod)%mod ); }
T2
首先預處理出來$c_i$為第i口井可以喝的次數
當前飛到第j次,ans為前j-1次喝到的水,$nu_i$為第i口井前面可以喝的井的數目
那麽第j次第i口井能喝到水,它必須滿足 $c_i$-$nu_i$>ans
那麽我們用線段樹維護$c_i$-$nu_i$的最小值
到了第j次飛,我們就把線段樹中$c_i$-$nu_i$<=ans的都取出來去掉,並且把i+1~n的值都+1
一直到第m次或沒有滿足條件的井了
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <cmath> #include <algorithm> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; inline int read() { char q=getchar();int ans=0; while(q<‘0‘||q>‘9‘)q=getchar(); while(q>=‘0‘&&q<=‘9‘){ans=ans*10+q-‘0‘;q=getchar();} return ans; } const int N=100006; const int INF=0x7fffffff-1e8; int n,m; int hi; int w[N],A[N],ci[N]; struct TTT______TTT { int mn[N*5],sum[N*5]; int ji[N*5]; inline void pushup(int x) { sum[x]=sum[x<<1]+sum[x<<1|1]; mn[x]=(mn[x<<1]<mn[x<<1|1]?mn[x<<1]:mn[x<<1|1]); } void pushdown(int x) { if(ji[x]) { ji[x<<1]+=ji[x]; ji[x<<1|1]+=ji[x]; mn[x<<1]+=ji[x]; mn[x<<1|1]+=ji[x]; ji[x]=0; } } void build(int l,int r,int x) { if(l==r) { mn[x]=ci[l]-l+1,sum[x]=1; return ; } int mid=(l+r)>>1; build(l,mid,x<<1); build(mid+1,r,x<<1|1); pushup(x); } void del(int pos,int l,int r,int x) { if(l==r) { mn[x]=INF;sum[x]=0; return ; } pushdown(x); int mid=(l+r)>>1; if(pos<=mid) del(pos,l,mid,x<<1); else del(pos,mid+1,r,x<<1|1); pushup(x); } void add(int L,int R,int l,int r,int x) { if(L>R) return ; if(L<=l&&r<=R) { ++mn[x];++ji[x]; return ; } pushdown(x); int mid=(l+r)>>1; if(L<=mid) add(L,R,l,mid,x<<1); if(mid<R) add(L,R,mid+1,r,x<<1|1); pushup(x); } int qqpos(int val,int l,int r,int x) { if(l==r) return l; pushdown(x); int mid=(l+r)>>1; if(mn[x<<1]==val) return qqpos(val,l,mid,x<<1); else return qqpos(val,mid+1,r,x<<1|1); } }T; int work() { T.build(1,n,1); int ans=0,temp; for(int i=1;i<=m;++i) { //printf("i=%d ans=%d\n",i,ans); while(T.mn[1]<=ans) { temp=T.qqpos(T.mn[1],1,n,1); //printf("mn=%d pos=%d\n",T.mn[1],temp); T.del(temp,1,n,1); T.add(temp+1,n,1,n,1); //cout<<0; } ans+=T.sum[1]; if(T.sum[1]==0) break; } return ans; } int main(){ freopen("T2.in","r",stdin); freopen("T2.out","w",stdout); n=read();m=read();hi=read(); for(int i=1;i<=n;++i) w[i]=read(); for(int i=1;i<=n;++i) A[i]=read(); for(int i=1;i<=n;++i) { ci[i]=(hi-w[i])/A[i]+1; if(ci[i]<0) ci[i]=0; } /*printf("\n"); for(int i=1;i<=n;++i) printf("%d ",ci[i]); printf("\n");*/ cout<<work(); }T2
T3
先把op==1||op==2的同一行(列)的並查集並起來,這樣可以減小建邊數量
然後tarjan一下,求最長鏈即可
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <cmath> #include <algorithm> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; inline int read() { char q=getchar();int ans=0; while(q<‘0‘||q>‘9‘)q=getchar(); while(q>=‘0‘&&q<=‘9‘){ans=ans*10+q-‘0‘;q=getchar();} return ans; } const int N=100006; const int RR=1000006; const int CC=1000006; struct son { int v,next; }; struct TTT___TTT { son a1[N*10]; int first[N*10],e; void clear() { mem(a1,0); mem(first,-1); e=0; } void addbian(int u,int v) { a1[e].v=v; a1[e].next=first[u]; first[u]=e++; } }h[2]; struct JI { int x,y,jian,jia,order; int op; void boom() { x=y=jian=jia=op=0x7fffffff; order=0; } }ji[N]; bool cmp_x(JI a,JI b) { if(a.x==b.x) return a.y<b.y; return a.x<b.x; } bool cmp_y(JI a,JI b) { if(a.y==b.y) return a.x<b.x; return a.y<b.y; } bool cmp_jian(JI a,JI b) { if(a.jian==b.jian) return a.jia<b.jia; return a.jian<b.jian; } bool cmp_jia(JI a,JI b) { if(a.jia==b.jia) return a.jian<b.jian; return a.jia<b.jia; } int fa[N]; int fin(int x) { if(fa[x]==-1) return x; fa[x]=fin(fa[x]); return fa[x]; } void match(int u,int v) { int x=fin(u),y=fin(v); if(x!=y) fa[x]=y; } int n,R,C; int zhan[N*5],he; int num[N]; int dfn[N],low[N],tim; bool flag[N]; int sum,sun[N],dui[N]; int an[N]; void dfs(int x) { int temp; an[x]=sun[x]; for(int i=h[1].first[x];i!=-1;i=h[1].a1[i].next) { temp=h[1].a1[i].v; if(an[temp]) { if(an[x]<an[temp]+sun[x]) an[x]=an[temp]+sun[x]; continue; } dfs(temp); if(an[x]<an[temp]+sun[x]) an[x]=an[temp]+sun[x]; } } void tarjan(int x) { dfn[x]=low[x]=++tim; zhan[++he]=x;flag[x]=1; int temp; for(int i=h[0].first[x];i!=-1;i=h[0].a1[i].next) { temp=h[0].a1[i].v; if(dfn[temp]==-1) { tarjan(temp); if(low[x]>low[temp]) low[x]=low[temp]; } else if(flag[temp]&&low[x]>low[temp]) low[x]=low[temp]; } if(low[x]==dfn[x]) { ++sum; while(1) { temp=zhan[he--];flag[temp]=0; dui[temp]=sum; sun[sum]+=num[temp]; if(temp==x) break; } } } void out11() { /*printf("\n"); for(int i=1;i<=n;++i) printf("%d ",fin(i)); printf("\n");*/ printf("\n"); for(int i=1;i<=n;++i) { printf("i=%d ",i); for(int j=h[0].first[i];j!=-1;j=h[0].a1[j].next) printf("%d ",h[0].a1[j].v); printf("\n"); } printf("\n"); } int work() { ji[0].boom();ji[n+1].boom(); sort(ji+1,ji+1+n,cmp_x); int now,t1,t2; for(int i=1;i<=n;i=now+1) { now=i;he=0; while(ji[now].x==ji[i].x&&now<=n) { if( ji[now].op==1 ) zhan[++he]=now; ++now; } --now; for(int j=2;j<=he;++j) match(ji[zhan[j]].order,ji[zhan[j-1]].order); } sort(ji+1,ji+1+n,cmp_y); for(int i=1;i<=n;i=now+1) { now=i;he=0; while(ji[now].y==ji[i].y&&now<=n) { if( ji[now].op==2 ) zhan[++he]=now; ++now; } --now; for(int j=2;j<=he;++j) match(ji[zhan[j]].order,ji[zhan[j-1]].order); } sort(ji+1,ji+1+n,cmp_x); for(int i=1;i<=n;i=now+1) { now=i;he=0; while(ji[now].x==ji[i].x&&now<=n) { if( ji[now].op==1 ) zhan[++he]=now; ++now; } --now; if(he) { t1=fin(ji[zhan[1]].order); for(int j=i;j<=now;++j) { t2=fin(ji[j].order); if(t1!=t2) h[0].addbian(t1,t2); } } for(int j=i;j<=now;++j) if(ji[j].op==3) { if(ji[j-1].x==ji[j].x&&ji[j-1].y==ji[j].y-1&&fin(ji[j].order)!=fin(ji[j-1].order)) h[0].addbian(fin(ji[j].order),fin(ji[j-1].order)); if(ji[j+1].x==ji[j].x&&ji[j+1].y==ji[j].y+1&&fin(ji[j].order)!=fin(ji[j+1].order)) h[0].addbian(fin(ji[j].order),fin(ji[j+1].order)); } } sort(ji+1,ji+1+n,cmp_y); for(int i=1;i<=n;i=now+1) { now=i;he=0; while(ji[now].y==ji[i].y&&now<=n) { if( ji[now].op==2 ) zhan[++he]=now; ++now; } --now; if(he) { t1=fin(ji[zhan[1]].order); for(int j=i;j<=now;++j) { t2=fin(ji[j].order); if(t1!=t2) h[0].addbian(t1,t2); } } for(int j=i;j<=now;++j) if(ji[j].op==3) { if(ji[j-1].y==ji[j].y&&ji[j-1].x==ji[j].x-1&&fin(ji[j].order)!=fin(ji[j-1].order)) h[0].addbian(fin(ji[j].order),fin(ji[j-1].order)); if(ji[j+1].y==ji[j].y&&ji[j+1].x==ji[j].x+1&&fin(ji[j].order)!=fin(ji[j+1].order)) h[0].addbian(fin(ji[j].order),fin(ji[j+1].order)); } } sort(ji+1,ji+1+n,cmp_jian); for(int i=1;i<=n;++i) if(ji[i].op==3) { t1=fin(ji[i].order); t2=fin(ji[i-1].order); if(ji[i-1].jian==ji[i].jian&&ji[i-1].jia==ji[i].jia-2&&t1!=t2) h[0].addbian(t1,t2); t2=fin(ji[i+1].order); if(ji[i+1].jian==ji[i].jian&&ji[i+1].jia==ji[i].jia+2&&t1!=t2) h[0].addbian(t1,t2); } sort(ji+1,ji+1+n,cmp_jia); for(int i=1;i<=n;++i) if(ji[i].op==3) { t1=fin(ji[i].order); t2=fin(ji[i-1].order); if(ji[i-1].jia==ji[i].jia&&ji[i-1].jian==ji[i].jian-2&&t1!=t2) h[0].addbian(t1,t2); t2=fin(ji[i+1].order); if(ji[i+1].jia==ji[i].jia&&ji[i+1].jian==ji[i].jian+2&&t1!=t2) h[0].addbian(t1,t2); } for(int i=1;i<=n;++i) ++num[fin(i)]; he=0; for(int i=1;i<=n;++i) if(dfn[i]==-1&&num[i]) tarjan(i); int temp; for(int i=1;i<=n;++i) if(num[i]) { for(int j=h[0].first[i];j!=-1;j=h[0].a1[j].next) { temp=h[0].a1[j].v; if(dui[i]!=dui[temp]) h[1].addbian(dui[i],dui[temp]); } } //out11(); //printf("sum=%d\n",sum); for(int i=1;i<=sum;++i) if(!an[i]) dfs(i); int ans=0; for(int i=1;i<=sum;++i) if(ans<an[i]) ans=an[i]; return ans; } int main(){ //freopen("T3.in","r",stdin); mem(fa,-1); mem(dfn,-1); h[0].clear(); h[1].clear(); n=read();R=read();C=read(); for(int i=1;i<=n;++i) { ji[i].x=read(); ji[i].y=read(); ji[i].op=read(); ji[i].jia=ji[i].x+ji[i].y; ji[i].jian=ji[i].x-ji[i].y; ji[i].order=i; } /*printf("\n"); for(int i=1;i<=n;++i) printf("%d %d %d\n",ji[i].x,ji[i].y,ji[i].op); printf("\n");*/ cout<<work(); }T3
總結:
多考慮每個題成立的條件,不要無頭緒的亂想
還有打程序要嚴謹...一遍對...
10.12 兩次考試