8.18题解

T1[BZOJ1856]

卡特兰数,和网格那道题相似度$99.99{\%}$

思路一

思路二

 1 #include<iostream>
 2 #include<cstdio>
 3 #define maxn 1001000
 4 #define ll long long
 5 using namespace std;
 6 const long long mod=20100403;
 7 int n,m;
 8 ll ans;
 9 ll jc[maxn*2],ny[maxn*2];
10 ll ksm(ll a,ll b)
11 {
12     ll ans=1;  a=a%mod;
13     while(b)
14     {
15         if(b&1)  ans=(ans*a)%mod;
16         b=b>>1;  a=(a*a)%mod;
17     }
18     return ans;
19 }
20 ll C(int x,int y)
21 {
22     return ((jc[x]*ny[y])%mod*ny[x-y])%mod;
23 }
24 int main()
25 {
26     scanf("%d%d",&n,&m);
27     jc[0]=1;
28     for(int i=1;i<=2*n;++i)  jc[i]=(jc[i-1]*i)%mod;
29     ny[2*n]=ksm(jc[2*n],mod-2);
30     for(int i=2*n;i>=1;--i)  ny[i-1]=(ny[i]*i)%mod;
31     ans=(C(n+m,n)-C(n+m,m-1)+mod)%mod;
32     printf("%lld\n",ans);
33     return 0;
34 }
没删freopen而WA0的代码

 

T2[BZOJ3441]

暴力模拟50分,优化暴力95分,然而考场上我打了个二分,考后迅速hack掉自己,考场没想到

正解用数据结构优化了模拟的过程

设$cnt[i]$代表第$i$个水缸最多可以下降几次,按$cnt$为关键字排序,$cnt$小的可以被喝的次数,对于$cnt$大的一定满足,所以答案可以直接转移,我们接下来需要做的是计算每个水缸对答案的贡献,我们枚举每一个水缸,尽量让每一个水缸剩余的水尽量少,先看这个水缸支持跳几遍n的水缸,然后用树状数组维护区间内可用水缸个数,二分查找当前水缸支持跳跃的最远的水缸继续转移下去即可

不懂可以去这个大佬那里膜拜一下

#include<algorithm>
#include<iostream>
#include<cstdio>
#define maxn 100100
using namespace std;
struct node{
    int cnt,pos;
}b[maxn];
int n,m,x,sum/*喝几次*/,tot/*喝几趟*/,poss/*乌鸦所在的位置*/;
int w[maxn],a[maxn],c[maxn]/*维护区间可用水缸个数*/;
bool cmp(const node &a,const node &b)
{
    return a.cnt<b.cnt;
}
int lowbit(int x)
{
    return x&(-x);
}
void add(int po,int w)
{
    for(;po<=n;po+=lowbit(po))  c[po]+=w;
}
int getsum(int po)
{
    int ans=0;
    for(;po;po-=lowbit(po))  ans+=c[po];
    return ans;
}
int ef(int w)
{
    int l=1,r=n,ANS=l;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        int Ans=getsum(mid)-getsum(poss);
        if(Ans>w)  r=mid-1;
        else  {l=mid+1;  ANS=mid;}
    }
    return ANS;
}
int main()
{
    scanf("%d%d%d",&n,&m,&x);
    for(int i=1;i<=n;++i)  scanf("%d",&w[i]);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&a[i]);
        b[i].cnt=(x-w[i])/a[i]+1;//计算当前水缸最多可以被喝几次
        b[i].pos=i;  add(i,1);
    }
    sort(b+1,b+n+1,cmp);
    for(int i=1;i<=n;++i)
    {
        //把不能继续被喝的直接搞掉,不做贡献
        if(b[i].cnt<sum)  {add(b[i].pos,-1);  continue;}
        //一个水缸最多能被喝几趟,之后就不能再喝一整趟
        //对于前面乌鸦停在了中间某个位置上,要先把剩余的水缸喝过去
        while(tot<m&&b[i].cnt>getsum(n)-getsum(poss)+sum)
        //当前水缸中剩下的水,在喝完前边喝过的次数之后,能否撑到后面的水缸都再喝一次
        //由于按可喝次数降序排列,前面的可以喝这么多次,那后面的有一定可以喝这么多次
            {sum+=getsum(n)-getsum(poss);  tot++;  poss=0;}
        if(tot>=m)  break;
        poss=ef(b[i].cnt-sum);//最多喝到第几个水缸就把当前水缸减没了,乌鸦现在停留在这个位置上
        //前面已经求得该水缸被喝b[i].cnt次是合法的,又由于排序,第i个合法,那么第i+1个一定是合法的
        sum=b[i].cnt;//直接继承,从poss开始,继续向后喝
        add(b[i].pos,-1);//当前水缸通过贪心,已经被喝到不能继续喝,直接去掉
    }
    printf("%d\n",sum);
    return 0;
}
View Code

 

T3[BZOJ1924]

轰炸那题一个思路,建图,tarjan缩点,拓扑即可,建图的时候只给藏宝宫室之间简便即可,和空宫室建边显然没用

 

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<vector>
  5 #include<stack>
  6 #include<queue>
  7 #define maxn 100100
  8 using namespace std;
  9 struct node{
 10     int x,y,opt,pos;
 11 };
 12 int n,r,c,js,tot,cnt,j,ans;
 13 int dfn[maxn],low[maxn],pd[maxn],ss[maxn],du[maxn];
 14 vector <node> cb;
 15 vector <node> h[maxn];
 16 vector <node> l[maxn];
 17 vector <int> so[maxn];
 18 vector <int> sh[maxn];
 19 vector <int> son[maxn];
 20 stack <int> s;
 21 queue <int> q;
 22 void tarjan(int x)
 23 {
 24     dfn[x]=low[x]=++tot;  pd[x]=1;  s.push(x);
 25     for(int i=0;i<son[x].size();++i)
 26     {
 27         int ls=son[x][i];
 28         if(!dfn[ls])  {tarjan(ls);  low[x]=min(low[x],low[ls]);}
 29         else if(pd[ls])  low[x]=min(low[x],dfn[ls]);
 30     }
 31     if(low[x]==dfn[x])
 32     {
 33         int y;  cnt++;
 34         do
 35         {
 36             y=s.top();  s.pop();
 37             pd[y]=0;  ss[y]=cnt;  sh[cnt].push_back(y);
 38         }
 39         while(y!=x);
 40     }
 41 }
 42 int main()
 43 {
 44     scanf("%d%d%d",&n,&r,&c);
 45     for(int i=1;i<=n;++i)
 46     {
 47         int o,p,q;  scanf("%d%d%d",&o,&p,&q);
 48         cb.push_back((node){o,p,q,i});
 49         h[o].push_back((node){o,p,q,i});
 50         l[p].push_back((node){o,p,q,i});
 51     }
 52     for(int i=0;i<cb.size();++i)
 53     {
 54         node ls=cb[i];
 55         if(ls.opt==1)
 56             for(int j=0;j<h[ls.x].size();++j)  son[ls.pos].push_back(h[ls.x][j].pos);
 57         if(ls.opt==2)
 58             for(int j=0;j<l[ls.y].size();++j)  son[ls.pos].push_back(l[ls.y][j].pos);
 59         if(ls.opt==3)
 60         {
 61             /*for(int j=0;j<cb.size();++j)
 62             {
 63                 node ls1=cb[j];
 64                 if(ls1.x==ls.x&&ls1.y==ls.y+1)  son[ls.pos].push_back(ls1.pos);
 65                 else if(ls1.x==ls.x&&ls1.y==ls.y-1)  son[ls.pos].push_back(ls1.pos);
 66                 else if(ls1.x==ls.x+1&&ls1.y==ls.y)  son[ls.pos].push_back(ls1.pos);
 67                 else if(ls1.x==ls.x-1&&ls1.y==ls.y)  son[ls.pos].push_back(ls1.pos);
 68                 else if(ls1.x==ls.x-1&&ls1.y==ls.y-1)  son[ls.pos].push_back(ls1.pos);
 69                 else if(ls1.x==ls.x-1&&ls1.y==ls.y+1)  son[ls.pos].push_back(ls1.pos);
 70                 else if(ls1.x==ls.x+1&&ls1.y==ls.y-1)  son[ls.pos].push_back(ls1.pos);
 71                 else if(ls1.x==ls.x+1&&ls1.y==ls.y+1)  son[ls.pos].push_back(ls1.pos);
 72             }*/
 73             for(int j=0;j<h[ls.x-1].size();++j)
 74                 if(h[ls.x-1][j].y==ls.y||h[ls.x-1][j].y==ls.y-1||h[ls.x-1][j].y==ls.y+1)
 75                     son[ls.pos].push_back(h[ls.x-1][j].pos);
 76             for(int j=0;j<h[ls.x+1].size();++j)
 77                 if(h[ls.x+1][j].y==ls.y||h[ls.x+1][j].y==ls.y-1||h[ls.x+1][j].y==ls.y+1)
 78                     son[ls.pos].push_back(h[ls.x+1][j].pos);
 79             for(int j=0;j<h[ls.x].size();++j)
 80                 if(h[ls.x][j].y==ls.y-1||h[ls.x][j].y==ls.y+1)
 81                     son[ls.pos].push_back(h[ls.x][j].pos);
 82         }
 83     }
 84     for(int i=1;i<=n;++i)
 85         if(!dfn[i])  tarjan(i);
 86     for(int i=1;i<=n;++i)
 87         for(int j=0;j<son[i].size();++j)
 88         {
 89             int ls=son[i][j];
 90             if(ss[i]!=ss[ls])
 91                 {so[ss[i]].push_back(ss[ls]);  du[ss[ls]]++;}
 92         }
 93     memset(pd,0,sizeof(pd));
 94     for(int i=1;i<=cnt;++i)
 95         if(!du[i])  {q.push(i);  pd[i]=sh[i].size();}
 96     while(q.size())
 97     {
 98         int ls=q.front();  q.pop();
 99         ans=max(ans,pd[ls]);
100         for(int i=0;i<so[ls].size();++i)
101         {
102             int lss=so[ls][i];  du[lss]--;
103             int js=sh[lss].size();
104             pd[lss]=max(js+pd[ls],pd[lss]);
105             if(du[lss]==0)  q.push(lss);
106             ans=max(ans,pd[lss]);
107         }
108     }
109     printf("%d\n",ans);
110     return 0;
111 }
View Code

 

posted @ 2019-08-18 20:54  hzoi_X&R  阅读(121)  评论(0编辑  收藏  举报