• [校内训练20_10_15]ABC


    A.雅礼集训convex

    回滚莫队:莫队时若发现删除、添加中有一个容易操作(O(1)),有一个不容易操作(>O(1))就可以使用这种方法。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long int ll;
      4 typedef long double ld;
      5 const int maxn=150005;
      6 int n,m;
      7 int len,rk[maxn],bel[maxn];
      8 ll ans[maxn];
      9 struct pt
     10 {
     11     ll x,y;
     12     int id;
     13     ld ra;
     14     ll operator*(const pt&A)const
     15     {
     16         return x*A.y-y*A.x;
     17     }
     18     bool operator<(const pt&A)const
     19     {
     20         return ra<A.ra;
     21     }
     22 }a[maxn],b[maxn];
     23 struct query
     24 {
     25     int l,r,id;
     26     bool operator<(const query&A)const
     27     {
     28         return bel[l]==bel[A.l]?r>A.r:bel[l]<bel[A.l];
     29     }
     30 }Q[maxn];
     31 inline void init()
     32 {
     33     for(int i=1;i<=n;++i)
     34         a[i].ra=atan2(a[i].y,a[i].x);
     35     sort(a+1,a+n+1);
     36     for(int i=1;i<=n;++i)
     37         rk[a[i].id]=i;
     38     len=sqrt(n);
     39 }
     40 int tot,head[555];
     41 int pre[maxn],nxt[maxn];
     42 int tmp[maxn];
     43 ll now;
     44 inline ll f(int x,int y)
     45 {
     46     return a[x]*a[y];
     47 }
     48 inline void doPre(int l)
     49 {
     50     now=0;
     51     memset(tmp,0,sizeof(tmp));
     52     memset(pre,0,sizeof(pre));
     53     memset(nxt,0,sizeof(nxt));
     54     for(int i=l;i<=n;++i)
     55         tmp[rk[i]]=i;
     56     int last=0,first=n+1;
     57     for(int i=1;i<=n;++i)
     58         if(tmp[i])
     59         {
     60             if(last)
     61             {
     62                 pre[i]=last;
     63                 nxt[last]=i;
     64                 now+=f(last,i);
     65             }
     66             last=i;
     67             first=min(first,i);
     68         }
     69     pre[first]=last;
     70     nxt[last]=first;
     71     now+=f(last,first);
     72 }
     73 inline void rem(int pos)
     74 {
     75     now-=f(pre[pos],pos)+f(pos,nxt[pos]);
     76     now+=f(pre[pos],nxt[pos]);
     77     nxt[pre[pos]]=nxt[pos];
     78     pre[nxt[pos]]=pre[pos];
     79 }
     80 inline ll ask(int L,int l)
     81 {
     82 //    cout<<"?? "<<L<<" "<<l<<endl;
     83     ll s=now;
     84     for(int i=L;i<l;++i)
     85     {
     86         int pos=rk[i];
     87         s-=f(pre[pos],pos)+f(pos,nxt[pos]);
     88         s+=f(pre[pos],nxt[pos]);
     89         nxt[pre[pos]]=nxt[pos];
     90         pre[nxt[pos]]=pre[pos];
     91     }
     92     for(int i=l-1;i>=L;--i)
     93     {
     94         int pos=rk[i];
     95         nxt[pre[pos]]=pos;
     96         pre[nxt[pos]]=pos;
     97     }
     98     return s;
     99 }
    100 inline void solve()
    101 {
    102     for(int i=1;i<=n;i+=len)
    103     {
    104         ++tot;
    105         bel[i]=tot;
    106         head[tot]=i;
    107     }
    108     for(int i=1;i<=n;++i)
    109         if(!bel[i])
    110             bel[i]=bel[i-1];
    111     sort(Q+1,Q+m+1);
    112     int pos=1;
    113     for(int i=1;i<=tot;++i)
    114     {
    115         doPre(head[i]);
    116         int r=n;
    117         while(bel[Q[pos].l]==i)
    118         {
    119             while(r>Q[pos].r)
    120                 rem(rk[r--]);
    121             ans[Q[pos].id]=ask(head[i],Q[pos].l);
    122             ++pos;
    123         }
    124     }
    125 }
    126 int main()
    127 {
    128 //    freopen("convex.in","r",stdin);
    129 //    freopen("convex.out","w",stdout);
    130     scanf("%d%d",&n,&m);
    131     for(int i=1;i<=n;++i)
    132     {
    133         scanf("%lld%lld",&a[i].x,&a[i].y);
    134         a[i].id=i;
    135     }
    136     for(int i=1;i<=m;++i)
    137     {
    138         scanf("%d%d",&Q[i].l,&Q[i].r);
    139         Q[i].id=i;
    140     }
    141     init();
    142     solve();
    143     for(int i=1;i<=m;++i)
    144         printf("%lld
    ",ans[i]);
    145     return 0;
    146 }
    View Code

    B.雅礼集训进攻

    容斥的想法:枚举最后的可行矩形,计算包含它的矩形个数,按照(-1)^(行数+列数)进行容斥。

    但这样没有任何拓展性!这又一次说明了容斥是多么的菜。

    直接统计的想法:尝试将难以考虑的整体转化为易于计数的部分。为了计算一个可行矩形的“1”的贡献,我们将其拆成1*1、1*2、2*1、2*2(这个可以重叠)的小矩形。可以发现,对于任何一个矩形,存在1=cnt(1*1)-cnt(1*2)-cnt(2*1)+cnt(2*2)。在所有可行情况中,某个位置上的cnt产生的总贡献是所有能够包含它的矩形的个数(当然,要k次方),而与包含了多少无关

    再考虑如何统计包含某个矩形的矩形个数。以1*1的矩形为例,最直接的方法是枚举所有可行的矩形,并把其中的每一个位置都加上1。我们把它差分成左上角加一、右上左下(要偏移一下)减一、右下加一,若我们能算出这个差分数组,就能在平方的复杂度内算出包含某个矩形的矩形个数。

    显然加一减一只和((以某个矩形为某一角,包含这个矩形)的矩形个数)有关。栈即可。

      1 #include<bits/stdc++.h>
      2 #define mod 998244353
      3 using namespace std;
      4 typedef long long int ll;
      5 const int maxn=2E3+5;
      6 int n,m,k;
      7 int a[maxn][maxn],sum[maxn][maxn],up[maxn][maxn],down[maxn][maxn];
      8 int tmp[maxn][maxn];
      9 ll ans;
     10 inline ll qpow(ll x,ll y)
     11 {
     12     ll ans=1,base=x;
     13     while(y)
     14     {
     15         if(y&1)
     16             ans=ans*base%mod;
     17         base=base*base%mod;
     18         y>>=1;
     19     }
     20     return ans;
     21 }
     22 inline void init()
     23 {
     24     for(int j=1;j<=m;++j)
     25         for(int i=1;i<=n;++i)
     26             if(a[i][j])
     27                 up[i][j]=up[i-1][j]+1;
     28     for(int j=1;j<=m;++j)
     29         for(int i=n;i>=1;--i)
     30             if(a[i][j])
     31                 down[i][j]=down[i+1][j]+1;
     32 }
     33 int b[maxn],q[maxn];
     34 inline ll get(int dx,int dy)
     35 {
     36     memset(tmp,0,sizeof(tmp));
     37     for(int i=1;i<=n;++i)
     38     {
     39         int sum=0,top=1;
     40         q[top]=m+1;
     41         for(int j=m;j>=1;--j)
     42         {
     43             b[j]=max(0,down[i][j]-dx+1);
     44             while(top&&b[j]<=b[q[top]])
     45             {
     46                 sum-=(q[top-1]-q[top])*b[q[top]];
     47                 --top;
     48             }
     49             sum+=(q[top]-j)*b[j];
     50             q[++top]=j;
     51             tmp[i][j]+=sum-(dy==2?b[j]:0);
     52         }
     53     }
     54     for(int i=1;i<=n;++i)
     55     {
     56         int sum=0,top=1;
     57         q[top]=0;
     58         for(int j=1;j<=m;++j)
     59         {
     60             b[j]=max(0,down[i][j]-dx+1);
     61             while(top&&b[j]<=b[q[top]])
     62             {
     63                 sum-=(q[top]-q[top-1])*b[q[top]];
     64                 --top;
     65             }
     66             sum+=(j-q[top])*b[j];
     67             q[++top]=j;
     68             tmp[i][j-dy+2]-=sum-(dy==2?b[j]:0);
     69         }
     70     }
     71     for(int i=1;i<=n;++i)
     72     {
     73         int sum=0,top=1;
     74         q[top]=m+1;
     75         for(int j=m;j>=1;--j)
     76         {
     77             b[j]=max(0,up[i][j]-dx+1);
     78             while(top&&b[j]<=b[q[top]])
     79             {
     80                 sum-=(q[top-1]-q[top])*b[q[top]];
     81                 --top;
     82             }
     83             sum+=(q[top]-j)*b[j];
     84             q[++top]=j;
     85             tmp[i-dx+2][j]-=sum-(dy==2?b[j]:0);
     86         }
     87     }
     88     for(int i=1;i<=n;++i)
     89     {
     90         int sum=0,top=1;
     91         q[top]=0;
     92         for(int j=1;j<=m;++j)
     93         {
     94             b[j]=max(0,up[i][j]-dx+1);
     95             while(top&&b[j]<=b[q[top]])
     96             {
     97                 sum-=(q[top]-q[top-1])*b[q[top]];
     98                 --top;
     99             }
    100             sum+=(j-q[top])*b[j];
    101             q[++top]=j;
    102             tmp[i-dx+2][j-dy+2]+=sum-(dy==2?b[j]:0);
    103         }
    104     }
    105     for(int i=1;i<=n;++i)
    106         for(int j=1;j<=m;++j)
    107             tmp[i][j]+=tmp[i-1][j]+tmp[i][j-1]-tmp[i-1][j-1];
    108     ll s=0;
    109     for(int i=1;i<=n;++i)
    110         for(int j=1;j<=m;++j)
    111             s+=qpow(tmp[i][j],k);
    112     return s;
    113 }
    114 inline void solve1()
    115 {
    116     ans=(ans+get(1,1))%mod;
    117 }
    118 inline void solve2()
    119 {
    120     ans=(ans-get(1,2))%mod;
    121     ans=(ans-get(2,1))%mod;
    122 }
    123 inline void solve3()
    124 {
    125     ans=(ans+get(2,2))%mod;
    126 }
    127 inline void solve()
    128 {
    129     solve1();
    130     solve2();
    131     solve3();
    132 }
    133 int main()
    134 {
    135     ios::sync_with_stdio(false);
    136     cin>>n>>m>>k;
    137     for(int i=1;i<=n;++i)
    138     {
    139         string str;
    140         cin>>str;
    141         for(int j=0;j<m;++j)
    142             a[i][j+1]=str[j]-'0';
    143     }
    144     init();
    145     solve();
    146     cout<<(ans%mod+mod)%mod<<endl;
    147     return 0;
    148 }
    View Code

    C.雅礼集训string

    首先看清题意!

    若我们算出了区间[l,r]的答案,那么新添或删去一个字符串相当于从trie树上新添或删去对应位置的字符串,然后统计增量。

    发现添加难,删除简单,还是回滚莫队。

    注意这里的分块要按串的总长来分。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long int ll;
      4 const int maxn=3E5+5;
      5 int n,m,ans[maxn];
      6 ll a[maxn],A,B,C,L,g[maxn];
      7 int len,tot,have[maxn],bel[maxn],tail[maxn],head[maxn],belW[maxn];
      8 char ch[maxn][26];
      9 string str[maxn];
     10 struct query
     11 {
     12     int l,r,id;
     13     bool operator<(const query&A)const
     14     {
     15         return bel[tail[l-1]+1]==bel[tail[A.l-1]+1]?r>A.r:bel[tail[l-1]+1]<bel[tail[A.l-1]+1];
     16     }
     17 }Q[maxn];
     18 inline void insert(string s)
     19 {
     20     int p=0;
     21     for(int i=0;i<s.size();++i)
     22     {
     23         int x=s[i]-'a';
     24         if(!ch[p][x])
     25             ch[p][x]=++tot;
     26         p=ch[p][x];
     27     }
     28 }
     29 inline void init()
     30 {
     31     len=sqrt(tail[n]);
     32     for(int i=1;i<=tail[n];++i)
     33         bel[i]=bel[i-1]+((i-1)%len==0);
     34     sort(Q+1,Q+m+1);
     35 }
     36 inline bool ok(int f,int len)
     37 {
     38     return f?B*f+A*len>=C:0;
     39 }
     40 ll now;
     41 int maxD,tmp[maxn],pre[maxn],nxt[maxn],inS[maxn];
     42 inline ll f(ll x,ll y)
     43 {
     44     return (x-y)*(x-y+1)/2;
     45 }
     46 int top,wait[maxn];
     47 inline void add(string str,int v)
     48 {
     49     int p=0,d=0;
     50     for(int i=0;i<str.size();++i)
     51     {
     52         p=ch[p][str[i]-'a'];
     53         ++d;
     54         int x=ok(have[p],d);
     55         have[p]+=v;
     56         int y=ok(have[p],d);
     57         if(x==1&&y==0)
     58         {
     59             x=g[d];
     60             --inS[x];
     61             if(inS[x]==0)
     62             {
     63                 now-=f(pre[x],x)+f(x,nxt[x]);
     64                 now+=f(pre[x],nxt[x]);
     65                 pre[nxt[x]]=pre[x];
     66                 nxt[pre[x]]=nxt[x];
     67                 wait[++top]=x;
     68             }
     69         }
     70         else if(x==0&&y==1)
     71             ++inS[g[d]];
     72     }
     73 }
     74 inline void bend()
     75 {
     76     while(top)
     77     {
     78         int x=wait[top];
     79         pre[nxt[x]]=x;
     80         nxt[pre[x]]=x;
     81         --top;
     82     }
     83 }
     84 inline void doPre(int l)
     85 {
     86     memset(tmp,0,sizeof(tmp));
     87     memset(inS,0,sizeof(inS));
     88     memset(nxt,0,sizeof(nxt));
     89     memset(pre,0,sizeof(pre));
     90     memset(have,0,sizeof(have));
     91     top=now=0;
     92     for(int i=l;i<=n;++i)
     93     {
     94         int p=0,d=0,v=a[i];
     95         for(int j=0;j<str[i].size();++j)
     96         {
     97             p=ch[p][str[i][j]-'a'];
     98             ++d;
     99             have[p]+=v;
    100             if(ok(have[p],d))
    101                 tmp[g[d]]=1,++inS[g[d]];
    102         }
    103     }
    104     int last=0;
    105     tmp[0]=tmp[maxD+1]=1;
    106     for(int i=0;i<=maxD+1;++i)
    107         if(tmp[i])
    108         {
    109             now+=f(last,i);
    110             nxt[last]=i;
    111             pre[i]=last;
    112             last=i;
    113         }
    114 }
    115 inline void solve()
    116 {
    117     for(int i=tail[n];i>=1;--i)
    118         head[bel[i]]=belW[i];
    119     int maxx=bel[tail[n]];
    120     int pos=1;
    121     for(int i=1;i<=maxx;++i)
    122     {
    123         int r=n;
    124         doPre(head[i]);
    125         while(bel[tail[Q[pos].l-1]+1]==i)
    126         {
    127         cout<<"?!?! "<<now<<endl;
    128             while(r>Q[pos].r)
    129             {
    130                 add(str[r],-a[r]);
    131                 --r;
    132                 top=0;
    133             }
    134             int l=head[i];
    135             ll g=now;
    136             while(l<Q[pos].l)
    137             {
    138                 add(str[l],-a[l]);
    139                 ++l;
    140             }
    141             ans[Q[pos].id]=now;
    142             bend();
    143             while(l>head[i])
    144             {
    145                 --l;
    146                 add(str[l],a[l]);
    147             }
    148             now=g;
    149             ++pos;
    150         }
    151     }
    152 }
    153 ll gcd(ll x,ll y)
    154 {
    155     return x%y==0?y:gcd(y,x%y);
    156 }
    157 int main()
    158 {
    159     freopen("string1.in","r",stdin);
    160     ios::sync_with_stdio(false);
    161     cin>>n>>A>>B>>C;
    162     for(int i=1;i<=n;++i)
    163         cin>>a[i];
    164     for(int i=1;i<=n;++i)
    165     {
    166         cin>>str[i];
    167         insert(str[i]);
    168         maxD=max(maxD,(int)str[i].size());
    169         tail[i]=tail[i-1]+str[i].size();
    170         for(int j=tail[i-1]+1;j<=tail[i];++j)
    171             belW[j]=i;
    172     }
    173     for(int i=1;i<=maxD;++i)
    174         cin>>g[i];
    175     cin>>m;
    176     for(int i=1;i<=m;++i)
    177     {
    178         cin>>Q[i].l>>Q[i].r;
    179         Q[i].id=i;
    180     }
    181     init();
    182     solve();
    183     ll tot=f(0,maxD+1);
    184     for(int i=1;i<=m;++i)
    185     {
    186         ans[i]=tot-ans[i];
    187         ll d=gcd(ans[i],tot);
    188         cout<<ans[i]/d<<"/"<<tot/d<<endl;
    189     }
    190     return 0;
    191 }
    View Code
  • 相关阅读:
    VML 和 SVG 的区别
    ie神器htc
    js函数实现递归自调用的方法
    http状态码
    高级算法——贪心算法(背包问题)
    高级算法——贪心算法(找零问题)
    关于arguments.callee
    检索算法——二分查找
    检索算法——顺序查找(最大值、最小值、自组织数据)
    高级排序算法——快速排序(一种分而治之的算法)
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/13824290.html
Copyright © 2020-2023  润新知