• cqoi2018


    题解:

    很多模板题

    第一次写莫队还比较顺利

    除了把排序的cmp写错。。(还第一次遇到)

    这题分块也可以

    先预处理出g[i][j]代表前i个块,颜色为j的有多少种

    f[i][j]表示i-j的块能构成多少对

    处理的方法就是f[i][j-1]+j块内和j与j之前

    算答案的时候即整块+两个单独块内部和两个单独块与整块之间

    因为分块有几个地方都是$nsqrt{n}$的 所以分块的常数比莫队要来的大

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rint register int
    
    #define IL inline
    
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    
    #define ll long long 
    
    #define me(x) memset(x,0,sizeof(x))
    
    namespace IO
    
    {
    
        char ss[1<<24],*A=ss,*B=ss;
    
        IL char gc()
    
        {
    
            return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
    
        }
    
        template<class T>void read(T &x)
    
        {
    
            rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
    
            while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
    
        }
    
        char sr[1<<24],z[20]; int Z,C=-1;
    
        template<class T>void wer(T x)
    
        {
    
            if (x<0) sr[++C]='-',x=-x;
    
            while (z[++Z]=x%10+48,x/=10);
    
            while (sr[++C]=z[Z],--Z);
    
        }
    
        IL void wer1()
    
        {
    
            sr[++C]=' ';
    
        }
    
        IL void wer2()
    
        {
    
            sr[++C]='
    ';
    
        }
    
        template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}
    
        template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}
    
        template<class T>IL T MAX(T x,T y){return x>y?x:y;}
    
        template<class T>IL T MIN(T x,T y){return x<y?x:y;}
    
    };
    
    using namespace IO;
    
    const int N=1e5+10;
    
    const int M=350;
    
    int n,m,k,block,q;
    
    int a[N],pos[N],b[N],now1[N],now2[N];
    
    ll ans2[N];
    
    struct re{
    
        int a,b,c;
    
    }p[N];
    
    ll ans=0;
    
    bool cmp(re x,re y)
    
    {
    
        return pos[x.a]<pos[y.a]||(pos[x.a]==pos[y.a]&&x.b<y.b);
    
    }
    
    IL void insert1(int x,int y)
    
    {
    
        if (y==1)
    
        {
    
          now2[b[x]]+=y;
    
          now1[b[x-1]]+=y;
    
        }
    
        ans+=now2[b[x-1]^k]*y;
    
        if (y==-1)
    
        {
    
          now2[b[x]]+=y;
    
          now1[b[x-1]]+=y;
    
        }
    
    }
    
    IL void insert2(int x,int y)
    
    {
    
        if (y==1)
    
        {
    
            now2[b[x]]+=y;
    
            now1[b[x-1]]+=y;
    
        }
    
        ans+=now1[b[x]^k]*y;
    
        if (y==-1)
    
        {
    
            now2[b[x]]+=y;
    
            now1[b[x-1]]+=y;
    
        }
    
    }
    
    int main()
    
    {
    
        freopen("1.in","r",stdin);
    
        freopen("1.out","w",stdout);
    
        read(n); read(q); read(k);
    
        rep(i,1,n) read(a[i]);
    
        block=sqrt(n);
    
        m=(n-1)/block+1;
    
        rep(i,1,n) pos[i]=(i-1)/block+1;
    
        rep(i,1,q)
    
          read(p[i].a),read(p[i].b),p[i].c=i;
    
        sort(p+1,p+q+1,cmp);
    
        rep(i,1,n) b[i]=b[i-1]^a[i];
    
        rep(i,p[1].a,p[1].b)
    
        {
    
            now1[b[i-1]]++;
    
            ans+=now1[b[i]^k];
    
            now2[b[i]]++;
    
        }
    
        ans2[p[1].c]=ans;
    
        rep(i,2,q)
    
        {
    
            if (p[i].a>p[i-1].a)
    
              rep(j,p[i-1].a,p[i].a-1)
    
                insert1(j,-1);
    
            else dep(j,p[i-1].a-1,p[i].a) insert1(j,1);
    
            if (p[i].b>p[i-1].b)
    
              rep(j,p[i-1].b+1,p[i].b) insert2(j,1);
    
            else dep(j,p[i-1].b,p[i].b+1) insert2(j,-1);
    
            ans2[p[i].c]=ans;
    
        }
    
        rep(i,1,q) wer(ans2[i]),wer2();
    
        fwrite(sr,1,C+1,stdout);
    
        return 0;
    
    }

    题目上面画个矩形下面用点真的是傻逼

    要是是矩形的画就比较麻烦 要判断4条边是否与那个线相交

    可以写特殊处理 当然也可以直接用计算几何里的线段与线段相交判定了

    要是直线的画直接叉积就可以了

    预处理一下再状压dp

    不太卡常

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define ll long long 
    #define me(x) memset(x,0,sizeof(x))
    namespace IO
    {
        char ss[1<<24],*A=ss,*B=ss;
        IL char gc()
        {
            return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
        }
        template<class T>void read(T &x)
        {
            rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
            while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
        }
        char sr[1<<24],z[20]; int Z,C=-1;
        template<class T>void wer(T x)
        {
            if (x<0) sr[++C]='-',x=-x;
            while (z[++Z]=x%10+48,x/=10);
            while (sr[++C]=z[Z],--Z);
        }
        IL void wer1()
        {
            sr[++C]=' ';
        }
        IL void wer2()
        {
            sr[++C]='
    ';
        }
        template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}
        template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}
        template<class T>IL T MAX(T x,T y){return x>y?x:y;}
        template<class T>IL T MIN(T x,T y){return x<y?x:y;}
    };
    using namespace IO;
    double ee=1.0000000000000000;
    const double eps=1e-9;
    const int N=(1<<20)+1000;
    const int mo=100000007;
    int n;
    int f[21][N];
    int p[40][40];
    struct re{
        int x,y;
    }a[40];
    IL void js(register int &x,register int y)
    {
        x=(x+y>mo)?x+y-mo:x+y;
    }
    int main()
    {
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
        read(n);
        rep(i,1,n)
        {
            read(a[i].x); read(a[i].y);
        }
        rep(i,1,n)
          rep(j,1,n)
            if (i!=j)
            rep(k,1,n)
            if (k!=i&&k!=j)
            {
              /*if (a[i].x==a[j].x)
              {
                if (a[k].x==a[i].x&&a[k].y>=MIN(a[i].y,a[j].y)&&a[k].y<=MAX(a[i].y,a[j].y))
                  p[i][j]|=(1<<(k-1));
              }
              else
              {
                  double now=ee*(a[j].y-a[i].y)/(a[j].x-a[i].x)*(a[k].x-a[i].x)+a[i].y;
                if (a[k].x<=MAX(a[i].x,a[j].x)&&a[k].x>=MIN(a[i].x,a[j].x)&&now+eps>a[k].y&&now<a[k].y+1) 
                  p[i][j]|=(1<<(k-1));
              }*/
              if (a[k].x<=MAX(a[i].x,a[j].x)&&a[k].x>=MIN(a[i].x,a[j].x)&&a[k].y<=MAX(a[i].y,a[j].y)&&a[k].y>=MIN(a[i].y,a[j].y)
                  &&(a[k].x-a[i].x)*(a[j].y-a[k].y)-(a[j].x-a[k].x)*(a[k].y-a[i].y)==0)
                    p[i][j]|=1<<(k-1);
            }
        rep(i,1,n) f[i][1<<(i-1)]=1;
        int l=(1<<n)-1;
        int ans=0;
        rep(i,1,l)
          rep(j,1,n)
            if (f[j][i])
            {
                rep(k,1,n)
                  if (((i>>(k-1))&1)==0&&(p[j][k]&(~i))==0) js(f[k][i|(1<<(k-1))],f[j][i]);
                if (__builtin_popcount(i)>=4) js(ans,f[j][i]);
            }
        wer(ans);
        fwrite(sr,1,C+1,stdout);
        return 0;
    }

    [CQOI2018]交错序列

    这可能是六题里唯一一题不是模板的题

    首先最暴力的做法

    就是$f[i][j][0/1]$表示前i个数有j个1且当前是0/1的方案数

    复杂度$O(n^2)$

    发现这个dp方程比较简单,考虑直接用数学方法求解

    先放1,然后再插空 答案就是$C(n-k+1,k)*k^a*(n-k)^b$

    这个东西$nlogn$ 因为模数比较小 所以组合数需要用lucas定理计算

    据游记所说这种做法好像并不能卡过?

    晚上写

    然后注意到这题a,b比较小

    考虑去展开$k^a*(n-k)^b$

    会发现我们只需要维护$k^{1~(a+b)}$就可以了

    然后$(k+1)^x$这个东西又可以用关于k的次方递推

    于是就可以上矩阵快速幂了

    时间复杂度$(a+b)^3*logn$

  • 相关阅读:
    计算机组成原理 04 认识各个硬件部件
    计算机组成原理 02 计算机的发展
    计算机组成原理 01 你好,计组
    蓝桥杯-2020-B组 &#183; 题解/解析(4/17)
    「HTML 5」1.HTML简介
    「易语言」主题颜色配置方案
    「易语言」那些年,我们经历的故事
    彻底解决Ubuntu中 “检测到系统程序错误”
    FFMPEG 的简单使用介绍 —— 合并音视频
    oh-my-zsh 中 agnoster主题 之 隐藏用户名信息
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/10018490.html
Copyright © 2020-2023  润新知