10.12 两次考试
上午的有些不可做...
等我成神犇之后再说吧...
下午的:
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;
const int 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();
}
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();
}
总结:
多考虑每个题成立的条件,不要无头绪的乱想
还有打程序要严谨...一遍对...