• 山东省第四届ACM程序设计竞赛部分题解


    A : Rescue The Princess

    题意:

    给你平面上的两个点A,B,求点C使得A,B,C逆时针成等边三角形。

    思路:

    http://www.cnblogs.com/E-star/archive/2013/06/11/3131563.html   向量的旋转。

    直接套公式就行,或者我们可以找到等式解一个二元一次方程然后向量判断方向即可。我比较懒,就写了向量旋转的。

    #include <iostream>  
    #include <cstdio>  
    #include <cmath>  
    #include <vector>  
    #include <cstring>  
    #include <algorithm>  
    #include <string>  
    #include <set>  
    #include <functional>  
    #include <numeric>  
    #include <sstream>  
    #include <stack>  
    #include <map>  
    #include <queue>  
      
    #define CL(arr, val)    memset(arr, val, sizeof(arr))  
      
    #define lc l,m,rt<<1  
    #define rc m + 1,r,rt<<1|1  
    #define pi acos(-1.0)  
    #define ll __int64  
    #define L(x)    (x) << 1  
    #define R(x)    (x) << 1 | 1  
    #define MID(l, r)   (l + r) >> 1  
    #define Min(x, y)   (x) < (y) ? (x) : (y)  
    #define Max(x, y)   (x) < (y) ? (y) : (x)  
    #define E(x)        (1 << (x))  
    #define iabs(x)     (x) < 0 ? -(x) : (x)  
    #define OUT(x)  printf("%I64d
    ", x)  
    #define lowbit(x)   (x)&(-x)  
    #define Read()  freopen("din.txt", "r", stdin)  
    #define Write() freopen("dout.txt", "w", stdout);  
      
      
    #define M 137  
    #define N 22  
      
    using namespace std;  
      
      
    const int inf = 0x7f7f7f7f;  
    const int mod = 1000000007;  
      
    double xx1,yy1,xx2,yy2;  
      
    int main()  
    {  
    //    Read();  
        int T;  
        scanf("%d",&T);  
        while (T--)  
        {  
            scanf("%lf%lf%lf%lf",&xx1,&yy1,&xx2,&yy2);  
    //        printf("%.3lf %.3lf %.3lf %.3lf
    ",xx1,yy1,xx2,yy2);  
            double tx = xx2 - xx1;  
            double ty = yy2 - yy1;  
      
            double x = tx*(1.0/2.0) - ty*(sqrt(3.0)/2.0) + xx1;  
            double y = ty*(1.0/2.0) + tx*(sqrt(3.0)/2.0) + yy1;  
            printf("(%.2lf,%.2lf)
    ",x,y);  
        }  
        return 0;  
    }  
    View Code

    B: Thrall’s Dream

    题意:

    给定n个点,m条有向边,求解任意两点是否可达。 

    思路:

    比赛时直接枚举每一个点,然后bfs判断就行,时间复杂度为O(n +m) , 这题tarjan缩点然后判断是否为链就行O(n + m)

    #include <iostream>  
    #include <cstdio>  
    #include <cmath>  
    #include <vector>  
    #include <cstring>  
    #include <algorithm>  
    #include <string>  
    #include <set>  
    #include <functional>  
    #include <numeric>  
    #include <sstream>  
    #include <stack>  
    #include <map>  
    #include <queue>  
      
    #define CL(arr, val)    memset(arr, val, sizeof(arr))  
      
    #define lc l,m,rt<<1  
    #define rc m + 1,r,rt<<1|1  
    #define pi acos(-1.0)  
    #define ll __int64  
    #define L(x)    (x) << 1  
    #define R(x)    (x) << 1 | 1  
    #define MID(l, r)   (l + r) >> 1  
    #define Min(x, y)   (x) < (y) ? (x) : (y)  
    #define Max(x, y)   (x) < (y) ? (y) : (x)  
    #define E(x)        (1 << (x))  
    #define iabs(x)     (x) < 0 ? -(x) : (x)  
    #define OUT(x)  printf("%I64d
    ", x)  
    #define lowbit(x)   (x)&(-x)  
    #define Read()  freopen("din.txt", "r", stdin)  
    #define Write() freopen("dout.txt", "w", stdout);  
      
      
    #define M 10007  
    #define N 2007  
      
    using namespace std;  
      
      
    const int inf = 0x7f7f7f7f;  
    const int mod = 1000000007;  
      
    struct node  
    {  
        int v;  
        int next;  
    }g[M];  
    int head[N],ct;  
    bool ok[N][N];  
    bool vt[N];  
    int n,m;  
      
    void add(int u,int v)  
    {  
        g[ct].v = v;  
        g[ct].next = head[u];  
        head[u] = ct++;  
    }  
    void bfs(int s)  
    {  
        int i;  
        for (i = 1; i <= n; ++i) vt[i] = false;  
        vt[s] = true;  
        queue<int> Q;  
        Q.push(s);  
        while (!Q.empty())  
        {  
            int u = Q.front(); Q.pop();  
            for (i = head[u]; i != -1; i = g[i].next)  
            {  
                int v = g[i].v;  
                if (!vt[v])  
                {  
                    vt[v] = true;  
                    ok[s][v] = true;  
                    Q.push(v);  
                }  
            }  
        }  
    }  
    int main()  
    {  
    //    Read();  
        int T;  
        int i,j;  
        scanf("%d",&T);  
        int cas = 1;  
        while (T--)  
        {  
           scanf("%d%d",&n,&m);  
           CL(head,-1); ct = 0;  
           int x,y;  
           for (i = 0; i < m; ++i)  
           {  
               scanf("%d%d",&x,&y);  
               add(x,y);  
           }  
           CL(ok,false);  
           for (i = 1; i <= n; ++i) ok[i][i] = true;  
           for (i = 1; i <= n; ++i) bfs(i);  
      
           bool flag = false;  
           for (i = 1; i <= n && !flag; ++i)  
           {  
               for (j = 1; j <= n && !flag; ++j)  
               {  
                   if (ok[i][j] || ok[j][i]) continue;  
                   else  
                   {  
                       flag = true;  
                       break;  
                   }  
               }  
           }  
           if (!flag) printf("Case %d: Kalimdor is just ahead
    ",cas++);  
           else printf("Case %d: The Burning Shadow consume us all
    ",cas++);  
        }  
        return 0;  
    }  
    View Code

    C: A^X mod P

    题意:

    题意很简单,看题就知道。 

    思路:

    在求A^X 幂时,快速幂求的话,是O(10^6*log(n)*40) = O(10^9) 肯定会超时,

    我们将X转化成 x = i*k + j。这样先在数组可以表示的范围内找到一个k,然后保存A^(1---k)的值,然后再将求出(A^k)^i 保存在数组里,这样每次求A^x,便可以通过这两个数组在O(1)的时间复杂度内求出来,这样时间复杂度就变成了O(10^6*40) = O(4*10^7)了

    #include <iostream>  
    #include <cstdio>  
    #include <cmath>  
    #include <vector>  
    #include <cstring>  
    #include <algorithm>  
    #include <string>  
    #include <set>  
    #include <functional>  
    #include <numeric>  
    #include <sstream>  
    #include <stack>  
    #include <map>  
    #include <queue>  
      
    #define CL(arr, val)    memset(arr, val, sizeof(arr))  
      
    #define lc l,m,rt<<1  
    #define rc m + 1,r,rt<<1|1  
    #define pi acos(-1.0)  
    #define ll long long  
    #define L(x)    (x) << 1  
    #define R(x)    (x) << 1 | 1  
    #define MID(l, r)   (l + r) >> 1  
    #define Min(x, y)   (x) < (y) ? (x) : (y)  
    #define Max(x, y)   (x) < (y) ? (y) : (x)  
    #define E(x)        (1 << (x))  
    #define iabs(x)     (x) < 0 ? -(x) : (x)  
    #define OUT(x)  printf("%I64d
    ", x)  
    #define lowbit(x)   (x)&(-x)  
    #define Read()  freopen("din.txt", "r", stdin)  
    #define Write() freopen("dout.txt", "w", stdout);  
      
      
    #define M 33333  
    #define N 31622  
    using namespace std;  
    const int mod = 1000000007;  
      
    ll powB[M + 10];  
    ll powA[N + 10];  
      
    ll n, A, K, a, b, m, P;  
      
    void init()  
    {  
        powA[0] = 1;  
        for (int i = 1; i <= N; ++i)  
        {  
            powA[i] = powA[i - 1]*A%P;  
        }  
        ll tmp = powA[N];  
        powB[0] = 1;  
        for (int i = 1; i <= M; ++i)  
        {  
            powB[i] = powB[i - 1]*tmp%P;  
        }  
    }  
    void solve(int cas)  
    {  
        ll fx = K;  
        ll ans = 0;  
        for (int i = 1; i <= n; ++i)  
        {  
            ans = (ans + powB[fx/N]*powA[fx%N]%P)%P;  
            fx = (a*fx + b)%m;  
        }  
        printf("Case #%d: %lld
    ",cas++,ans);  
    }  
    int main()  
    {  
        int T;  
        int cas = 1;  
        scanf("%d",&T);  
      
        while (T--)  
        {  
            cin>>n>>A>>K>>a>>b>>m>>P;  
            init();  
            solve(cas++);  
        }  
        return 0;  
    }  
       
    View Code

    D: Rubik’s cube

    好像是个模拟题,还没写

    E: Mountain Subsequences

    题意:

    给你一个长度为m的字符串仅由小写英文字母组成,求满足a1 < ...< ai < ai+1 < Amax > aj > aj+1 > ... > an的子串的个数

    思路:
    首先它仅包含26个英文字母,我们只要枚举每一个位置,然后记录每个位置左边满足条件的个数,右边满足条件的个数,最后乘起来就是了,那么我们怎么记录左边,右边满足的个数的呢?

    dp[c]表示以字符c结尾的满足情况的个数,dl[i]表示第i个位置左边满足条件的个数,dr[i]表示第i个位置右边满足条件的个数,

    dp[c] = (dl[i] + 1);  s[i] = c; 1表示的s[i]单独一个时满足的情况,dl[i]表示他左边的满足的各种情况+s[i] 后满足情况的。

    #include <iostream>  
    #include <cstdio>  
    #include <cmath>  
    #include <vector>  
    #include <cstring>  
    #include <algorithm>  
    #include <string>  
    #include <set>  
    #include <functional>  
    #include <numeric>  
    #include <sstream>  
    #include <stack>  
    #include <map>  
    #include <queue>  
      
    #define CL(arr, val) memset(arr, val, sizeof(arr))  
      
    #define lc l,m,rt<<1  
    #define rc m + 1,r,rt<<1|1  
    #define pi acos(-1.0)  
    #define ll long long  
    #define L(x)    (x) << 1  
    #define R(x)    (x) << 1 | 1  
    #define MID(l, r)   (l + r) >> 1  
    #define Min(x, y)   (x) < (y) ? (x) : (y)  
    #define Max(x, y)   (x) < (y) ? (y) : (x)  
    #define E(x)        (1 << (x))  
    #define iabs(x)     (x) < 0 ? -(x) : (x)  
    #define OUT(x)  printf("%I64d
    ", x)  
    #define lowbit(x)   (x)&(-x)  
    #define Read()  freopen("data.in", "r", stdin)  
    #define Write() freopen("d.out", "w", stdout)  
      
      
    #define M 100007  
    #define N 100007  
      
    using namespace std;  
      
      
    const int inf = 0x7f7f7f7f;  
    const int mod = 1000000007;  
    int dp[27],dl[N],dr[N];  
    int n;  
    char ts[N];  
    int s[N];  
      
    int main()  
    {  
    //    Read();  
        int i,j;  
        while (~scanf("%d",&n))  
        {  
            scanf("%s",ts);  
            for (i = 0; i < n; ++i) s[i] = ts[i] - 'a';  
      
            CL(dp,0); CL(dl,0); CL(dr,0);  
      
            for (i = 0; i < n; ++i)  
            {  
                for (j = 0; j < s[i]; ++j) dl[i] += dp[j];  
      
                dl[i] %= 2012;  
                dp[s[i]] += (dl[i] + 1);  
                dp[s[i]] %= 2012;  
            }  
      
            CL(dp,0);  
            for (i = n - 1; i >= 0; --i)  
            {  
                for (j = 0; j < s[i]; ++j) dr[i] += dp[j];  
      
                dr[i] %= 2012;  
                dp[s[i]] += (dr[i] + 1);  
                dp[s[i]] %= 2012;  
            }  
            int ans = 0;  
            for (i = 0; i < n; ++i)  
            {  
                ans += dl[i]*dr[i];  
                ans %= 2012;  
            }  
            printf("%d
    ",ans);  
        }  
        return 0;  
    }  
    View Code

    F: Alice and Bob

    题意:

    给出一个多项式:(a0*x^(2^0)+1) * (a1 * x^(2^1)+1)*.......*(an-1 * x^(2^(n-1))+1)

    输入P,求X^p 前边的系数。

    思路:

    首先P肯定是一个二进制表示的数,并且唯一。我们只要将p转化成二进制数,然后乘上系数就好了。

    #include <iostream>  
    #include <cstdio>  
    #include <cmath>  
    #include <vector>  
    #include <cstring>  
    #include <algorithm>  
    #include <string>  
    #include <set>  
    #include <functional>  
    #include <numeric>  
    #include <sstream>  
    #include <stack>  
    #include <map>  
    #include <queue>  
       
    #define CL(arr, val)    memset(arr, val, sizeof(arr))  
       
    #define lc l,m,rt<<1  
    #define rc m + 1,r,rt<<1|1  
    #define pi acos(-1.0)  
    #define ll long long  
    #define L(x)    (x) << 1  
    #define R(x)    (x) << 1 | 1  
    #define MID(l, r)   (l + r) >> 1  
    #define Min(x, y)   (x) < (y) ? (x) : (y)  
    #define Max(x, y)   (x) < (y) ? (y) : (x)  
    #define E(x)        (1 << (x))  
    #define iabs(x)     (x) < 0 ? -(x) : (x)  
    #define OUT(x)  printf("%I64d
    ", x)  
    #define lowbit(x)   (x)&(-x)  
    #define Read()  freopen("din.txt", "r", stdin)  
    #define Write() freopen("dout.txt", "w", stdout);  
       
       
    #define M 137  
    #define N 55  
       
    using namespace std;  
       
       
    const int inf = 0x7f7f7f7f;  
    const int mod = 1000000007;  
       
    int a[N],b[60];  
       
    int main()  
    {  
       int T,i;  
       int n,m;  
       scanf("%d",&T);  
       while (T--)  
       {  
           scanf("%d",&n);  
           CL(a,0);  
           for (i = 0; i < n; ++i) scanf("%d",&a[i]);  
       
           scanf("%d",&m);  
           int top;  
           ll p;  
           while (m--)  
           {  
               cin>>p; top = 0;  
               if (p == 0)  
               {  
                   printf("1
    ");  
                   continue;  
               }  
               while (p)  
               {  
                   b[top++] = p%2;  
                   p /= 2;  
               }  
               int ans = 1;  
               for (i = 0; i < top; ++i)  
               {  
                   if (b[i])  ans = ans*a[i]%2012;  
               }  
       
              printf("%d
    ",ans);  
           }  
       }  
       return 0;  
    }   
      
    View Code

    G: A-Number and B-Number

    题意:
    给出Anum的定义,包含7或者能被7整除的数,

    然后给出Bnum的定义,a[i] = Anum 表示i不是Anum

    输入n输出第n个Bnum

    思路:

    二分 + 数位DP

    首先我们二分一个数mid,找到<=mid的mid最小的区间满足等于n个Bnum的数,那么这个数肯定是Bnum。

    关键是如何求区间内Bnum的数量,我们转化为先求一下Anum的数量,然后对Anum数量这个区间再求Anum数量就得到了这个区间Bnum的数量了。在求Anum数量时就用到了数位DP

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <string>
    #include <set>
    #include <functional>
    #include <numeric>
    #include <sstream>
    #include <stack>
    #include <map>
    #include <queue>
     
    #define CL(arr, val) memset(arr, val, sizeof(arr))
     
    #define lc l,m,rt<<1
    #define rc m + 1,r,rt<<1|1
    #define pi acos(-1.0)
    #define L(x)    (x) << 1
    #define R(x)    (x) << 1 | 1
    #define MID(l, r)   (l + r) >> 1
    #define Min(x, y)   (x) < (y) ? (x) : (y)
    #define Max(x, y)   (x) < (y) ? (y) : (x)
    #define E(x)        (1 << (x))
    #define iabs(x)     (x) < 0 ? -(x) : (x)
    #define OUT(x)  printf("%I64d
    ", x)
    #define lowbit(x)   (x)&(-x)
    #define Read()  freopen("data.in", "r", stdin)
    #define Write() freopen("d.out", "w", stdout)
    #define ll unsigned long long
     
     
    #define M 100007
    #define N 100007
     
    using namespace std;
     
    const int inf = 0x7f7f7f7f;
    const int mod = 1000000007;
     
    const ll R = ((1uLL<<63) - 1);
     
    ll dp[25][7][2];
    int bit[25];
    ll n;
     
    ll dfs(int len,int pre,int flag,int limit)
    {
        if (len == -1) return flag||pre == 0;
        if (!limit && dp[len][pre][flag] != -1uLL) return dp[len][pre][flag];
     
        int up = limit?bit[len]:9;
        ll ans = 0;
        for (int i = 0; i <= up; ++i)
        {
            int tpre = (pre*10 + i)%7;
            int tflag = (flag || i == 7);
            int tlimit = (limit && i == up);
            ans += dfs(len - 1,tpre,tflag,tlimit);
        }
        if (!limit) dp[len][pre][flag] = ans;
        return ans;
    }
    ll getR(ll m)
    {
        int len  = 0;
        while (m)
        {
            bit[len++] = m%10;
            m /= 10;
        }
        return dfs(len - 1,0,0,1) - 1;
    }
    ll solve(ll m)
    {
        ll cnt1 = getR(m);
        ll cnt2 = cnt1 - getR(cnt1);
        return cnt2;
    }
    int main()
    {
    //    Read();
        while (~scanf("%lld",&n))
        {
            CL(dp,-1);
            ll l = 0,r = R;
            ll ans = 0;
            while (l <= r)
            {
                ll mid = (l + r)>>1;
                if (solve(mid) < n) l = mid + 1;
                else
                {
                    ans = mid;
                    r = mid - 1;
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
     
    View Code

    H: Boring Counting

    题意:

    给你n个数,m个询问(N and M (1 <= N, M <= 50000)),询问包含四个数L,R,A,B 求区间[L,R]里面在区间[A,B]的数的个数。

    思路:

    首先想到的是二维树状数组,或者二维线段树处理,因为数据量太大。但是二维这个维数也不能表示,因为离散化之后50000*50000是不能表示的,那怎么办呢?

    划分树,我们只要二分枚举该区间的最小的第几大大于等于A,以及最小的大于B的第几大,然后他们的差值就区间满足条件的个数。时间复杂度为O(nlog(n)*log(n));

    这里求区间第几大用到了划分树。

    #include <iostream>  
    #include <cstdio>  
    #include <cmath>  
    #include <vector>  
    #include <cstring>  
    #include <algorithm>  
    #include <string>  
    #include <set>  
    #include <functional>  
    #include <numeric>  
    #include <sstream>  
    #include <stack>  
    #include <map>  
    #include <queue>  
      
    #define CL(arr, val)    memset(arr, val, sizeof(arr))  
      
    #define lc l,m,rt<<1  
    #define rc m + 1,r,rt<<1|1  
    #define pi acos(-1.0)  
    #define ll __int64  
    #define L(x)    (x) << 1  
    #define R(x)    (x) << 1 | 1  
    #define MID(l, r)   (l + r) >> 1  
    #define Min(x, y)   (x) < (y) ? (x) : (y)  
    #define Max(x, y)   (x) < (y) ? (y) : (x)  
    #define E(x)        (1 << (x))  
    #define iabs(x)     (x) < 0 ? -(x) : (x)  
    #define OUT(x)  printf("%I64d
    ", x)  
    #define Read()  freopen("din.txt", "r", stdin)  
    #define Write() freopen("dout.in", "w", stdout);  
      
      
    #define M 50007  
    #define N 50007  
      
    using namespace std;  
      
      
    const int inf = 0x7f7f7f7f;  
      
    struct node{  
        int l,r;  
        int mid(){  
            return (l + r)>>1;  
        }  
    }tt[N<<2];  
    int toLeft[30][N];  
    int val[30][N],sorted[N];  
    int n,q,m;  
      
    void build(int l,int r,int rt,int d){  
        int i;  
        tt[rt].l = l;  
        tt[rt].r = r;  
        if (l == r) return ;  
        int m = tt[rt].mid();  
        int lsame = m - l + 1;  
      
        for (i = l; i <= r; ++i){  
            if (val[d][i] < sorted[m]) lsame--;  
        }  
      
        int lpos = l;  
        int rpos = m + 1;  
        int same = 0;  
      
        for (i = l; i <= r; ++i){  
            if (i == l) toLeft[d][i] = 0;  
            else toLeft[d][i] = toLeft[d][i - 1];  
      
            if (val[d][i] < sorted[m]){  
                toLeft[d][i]++;  
                val[d + 1][lpos++] = val[d][i];  
            }  
            else if (val[d][i] > sorted[m]){  
                val[d + 1][rpos++] = val[d][i];  
            }  
            else{  
                if (same < lsame){  
                    toLeft[d][i]++;  
                    val[d + 1][lpos++] = val[d][i];  
                    same++;  
                }  
                else{  
                    val[d + 1][rpos++] = val[d][i];  
                }  
            }  
        }  
        build(lc,d + 1);  
        build(rc,d + 1);  
    }  
      
    int query(int L,int R,int k,int d,int rt){  
        if (L == R){  
            return val[d][L];  
        }  
        int s = 0;  
        int ss = 0;  
        if (L == tt[rt].l){  
            ss = 0;  
            s = toLeft[d][R];  
        }  
        else{  
            ss = toLeft[d][L - 1];  
            s = toLeft[d][R] - toLeft[d][L - 1];  
        }  
        if (k <= s){  
            int newl = tt[rt].l + ss;  
            int newr = newl + s - 1;  
            return query(newl,newr,k,d + 1,rt<<1);  
        }  
        else{  
            int m = tt[rt].mid();  
            int bb = L - tt[rt].l - ss;  
            int b = R - L + 1 - s;  
            int newl = m + bb + 1;  
            int newr = newl + b - 1;  
            return query(newl,newr,k - s,d + 1,rt<<1|1);  
        }  
    }  
    int BS1(int L,int R,int l,int r,int A)  
    {  
        int ans = -1;  
        while (l <= r)  
        {  
            int mid = (l + r)>>1;  
            int res = query(L,R,mid,0,1);  
            if (res >= A)  
            {  
                ans = mid;  
                r = mid - 1;  
            }  
            else l = mid + 1;  
        }  
        return ans;  
    }  
    int BS2(int L,int R,int l,int r,int B)  
    {  
        int ans = 0;  
        while (l <= r)  
        {  
            int mid = (l + r)>>1;  
            int res = query(L,R,mid,0,1);  
            if (res > B)  
            {  
                ans = mid;  
                r = mid - 1;  
            }  
            else l = mid + 1;  
        }  
        if (ans == 0) return r;  
        else return ans - 1;  
    }  
    int main()  
    {  
    //    Read();  
      
        int T,i;  
        int cas = 1;  
        scanf("%d",&T);  
        while (T--)  
        {  
            scanf("%d%d",&n,&m);  
            for (i = 1; i <= n; ++i)  
            {  
                scanf("%d",&val[0][i]);  
                sorted[i] = val[0][i];  
            }  
            sort(sorted + 1,sorted + 1 + n);  
            build(1,n,1,0);  
      
            printf("Case #%d:
    ",cas++);  
            int x,y,A,B;  
            while (m--)  
            {  
                scanf("%d%d%d%d",&x,&y,&A,&B);  
      
                int l = 1;  
                int r = y - x + 1;  
                int cnt1 = BS1(x,y,l,r,A);  
                int cnt2 = BS2(x,y,l,r,B);  
    //            printf(">>>>%d %d %d %d %d %d
    ",x,y,A,B,cnt1,cnt2);  
                if (cnt1 == -1)  
                {  
                    printf("0
    ");  
                    continue;  
                }  
                printf("%d
    ",cnt2 - cnt1 + 1);  
            }  
        }  
        return 0;  
    }  
       
    View Code

    有没有更优的解法,当然有。  我们回到二维树状数组,如果我们求一个矩阵内的和的话,需要知道四个点到源点的的和,然后根据简单的容斥弄出来。这里我们将每个询问离线处理,转化成四个点,然后将点按x轴(表示[l,R])排序,y轴呢则表示[A,B]这样没当插入一点的时候我们就将小于x的所有的给定序列的值查到纵轴所标的区间内,纵轴用一个一维的树状数组即可,然后每当遇到四个点中的所要求的点的时候,计算就行,因为这样保证了纵轴上的点肯定是在[L,R]范围内的,然后我们在根据[A,B]来求一维的值即可。

    #include <iostream>  
    #include <cstdio>  
    #include <cmath>  
    #include <vector>  
    #include <cstring>  
    #include <algorithm>  
    #include <string>  
    #include <set>  
    #include <functional>  
    #include <numeric>  
    #include <sstream>  
    #include <stack>  
    #include <map>  
    #include <queue>  
      
    #define CL(arr, val)    memset(arr, val, sizeof(arr))  
      
    #define lc l,m,rt<<1  
    #define rc m + 1,r,rt<<1|1  
    #define pi acos(-1.0)  
    #define ll __int64  
    #define L(x)    (x) << 1  
    #define R(x)    (x) << 1 | 1  
    #define MID(l, r)   (l + r) >> 1  
    #define Min(x, y)   (x) < (y) ? (x) : (y)  
    #define Max(x, y)   (x) < (y) ? (y) : (x)  
    #define E(x)        (1 << (x))  
    #define iabs(x)     (x) < 0 ? -(x) : (x)  
    #define OUT(x)  printf("%I64d
    ", x)  
    #define Read()  freopen("din.txt", "r", stdin)  
    #define Write() freopen("dout.in", "w", stdout);  
      
      
    #define M 50007  
    #define N 50007  
      
    using namespace std;  
      
      
    const int inf = 0x7f7f7f7f;  
      
    struct point  
    {  
        int x,y;  
        int id;  
        int no;  
    }pt[10*N];  
    int SM[10*N];  
      
    int n,m;  
    int c[10*N],a[N],b[10*N];  
    int of[N*10][6];  
    int ans[N];  
      
    int nn;  
      
    int lowbit(int x)  
    {  
        return (x&(-x));  
    }  
    void modify(int pos,int val)  
    {  
        while (pos <= nn)  
        {  
            c[pos] += val;  
            pos += lowbit(pos);  
        }  
    }  
    int getsum(int pos)  
    {  
        int sum = 0;  
        while (pos > 0)  
        {  
            sum += c[pos];  
            pos -= lowbit(pos);  
        }  
        return sum;  
    }  
    int BS(int l,int r,int val)  
    {  
        while (l <= r)  
        {  
            int mid = (l + r)/2;  
            if (b[mid] == val) return mid;  
            else if (b[mid] < val) l = mid + 1;  
            else r = mid - 1;  
        }  
        return -1;  
    }  
    int cmp(int x,int y)  
    {  
        return x < y;  
    }  
    int cmpPt(point a,point b)  
    {  
        if (a.x != b.x) return a.x < b.x;  
        else return a.y < b.y;  
    }  
    int main()  
    {  
    //    Read();  
    //    Write();  
        int T,i;  
        int cas = 1;  
        scanf("%d",&T);  
        while (T--)  
        {  
            scanf("%d%d",&n,&m);  
            int k = 0;  
            for (i = 1; i <= n; ++i)  
            {  
                scanf("%d",&a[i]);  
                b[++k] = a[i];  
            }  
      
            int pl = 0;  
            int x1,y1,x2,y2;  
            for (i = 1; i <= m; ++i)  
            {  
                scanf("%d%d%d%d",&x1,&x2,&y1,&y2);  
                b[++k] = y1 - 1; b[++k] = y2;  
      
                pt[pl].x = x1 - 1, pt[pl].y = y1 - 1;  
                pt[pl].id = i,pt[pl++].no = 0;  
      
                pt[pl].x = x1 - 1, pt[pl].y = y2;  
                pt[pl].id = i,pt[pl++].no = 1;  
      
                pt[pl].x = x2, pt[pl].y = y1 - 1;  
                pt[pl].id = i,pt[pl++].no = 2;  
      
                pt[pl].x = x2, pt[pl].y = y2;  
                pt[pl].id = i,pt[pl++].no = 3;  
            }  
      
            sort(b + 1,b + 1 + k,cmp); nn = 1;  
            for (i = 2; i <= k; ++i) if (b[i] != b[i - 1]) b[++nn] = b[i];  
      
            sort(pt,pt + pl,cmpPt);  
            for (i = 0; i < pl; ++i) of[pt[i].id][pt[i].no] = i;  
      
      
            CL(c,0); CL(ans,0);  
            int s = 1;  
            for (i = 0; i < pl; ++i)  
            {  
                int x = pt[i].x;  
                int y = pt[i].y;  
                for (; s <= x; ++s)  
                {  
                    int pos = BS(1,nn,a[s]);  
                    modify(pos,1);  
                }  
                int p = BS(1,nn,y);  
                SM[i] = getsum(p);  
                if (pt[i].no == 3)  
                {  
                    int id = pt[i].id;  
                    ans[id] = SM[i] - SM[of[id][1]] - SM[of[id][2]] + SM[of[id][0]];  
                }  
            }  
            printf("Case #%d:
    ",cas++);  
            for (i = 1; i <= m; ++i) printf("%d
    ",ans[i]);  
        }  
        return 0;  
    }  
    View Code

    I:The number of steps

    题意:

    迷宫是由一个如下的图形组成

         1

        2 3

       4 5 6

     7 8 9 10

    ...

    起始点在1,规定只能望左,左下,右下走,如果不存在左边的点的话,那么往左下,右下的概率为a,b,如果三个点都存在的话,那么往左,左下,右下的概率分别为e,c,d, 如果仅存在左边的点的话,那么走左边点的概率为1

    求到达最底层的左下角的点的所用步数的概率。

    思路:

    很简单的一个概率DP的题目,和置筛子的题目类似。 一定要明白为什么倒着推

    学习链接:http://kicd.blog.163.com/blog/static/126961911200910168335852/

    #include <iostream>  
    #include <cstdio>  
    #include <cmath>  
    #include <vector>  
    #include <cstring>  
    #include <algorithm>  
    #include <string>  
    #include <set>  
    #include <functional>  
    #include <numeric>  
    #include <sstream>  
    #include <stack>  
    #include <map>  
    #include <queue>  
       
    #define CL(arr, val) memset(arr, val, sizeof(arr))  
       
    #define lc l,m,rt<<1  
    #define rc m + 1,r,rt<<1|1  
    #define pi acos(-1.0)  
    #define ll long long  
    #define L(x)    (x) << 1  
    #define R(x)    (x) << 1 | 1  
    #define MID(l, r)   (l + r) >> 1  
    #define Min(x, y)   (x) < (y) ? (x) : (y)  
    #define Max(x, y)   (x) < (y) ? (y) : (x)  
    #define E(x)        (1 << (x))  
    #define iabs(x)     (x) < 0 ? -(x) : (x)  
    #define OUT(x)  printf("%I64d
    ", x)  
    #define lowbit(x)   (x)&(-x)  
    #define Read()  freopen("data.in", "r", stdin)  
    #define Write() freopen("d.out", "w", stdout)  
       
       
    #define M 100007  
    #define N 57  
       
    using namespace std;  
       
    const int inf = 0x7f7f7f7f;  
    const int mod = 1000000007;  
       
    double dp[N][N];  
    double a, b, c, d, e;  
       
    int main()  
    {  
    //    Read();  
        int n;  
        while (~scanf("%d",&n))  
        {  
            if (!n) break;  
            cin>>a>>b>>c>>d>>e;  
            CL(dp,0);  
            dp[n][1] = 0;  
            for (int i = 1; i <= n - 1; ++i)  
            {  
                dp[n][i + 1] += (dp[n][i] + 1);  
            }  
       
            for (int i = n - 1; i >= 1; --i)  
            {  
                dp[i][1] += (dp[i + 1][1] + 1)*a + (dp[i + 1][2] + 1)*b;  
                for (int j = 2; j <= i; ++j)  
                {  
                    dp[i][j] += (dp[i + 1][j] + 1)*c + (dp[i + 1][j + 1] + 1)*d + (dp[i][j - 1] + 1)*e;  
                }  
            }  
       
            printf("%.2lf
    ",dp[1][1]);  
        }  
        return 0;  
    }  
    View Code

    J:Contest Print Server

    坑爹的大水题,什么也不说了。

    #include <iostream>  
    #include <cstdio>  
    #include <cmath>  
    #include <vector>  
    #include <cstring>  
    #include <algorithm>  
    #include <string>  
    #include <set>  
    #include <functional>  
    #include <numeric>  
    #include <sstream>  
    #include <stack>  
    #include <map>  
    #include <queue>  
      
    #define CL(arr, val)    memset(arr, val, sizeof(arr))  
      
    #define lc l,m,rt<<1  
    #define rc m + 1,r,rt<<1|1  
    #define pi acos(-1.0)  
    #define ll __int64  
    #define L(x)    (x) << 1  
    #define R(x)    (x) << 1 | 1  
    #define MID(l, r)   (l + r) >> 1  
    #define Min(x, y)   (x) < (y) ? (x) : (y)  
    #define Max(x, y)   (x) < (y) ? (y) : (x)  
    #define E(x)        (1 << (x))  
    #define iabs(x)     (x) < 0 ? -(x) : (x)  
    #define OUT(x)  printf("%I64d
    ", x)  
    #define lowbit(x)   (x)&(-x)  
    #define Read()  freopen("din.txt", "r", stdin)  
    #define Write() freopen("dout.txt", "w", stdout);  
      
      
    #define M 10007  
    #define N 107  
      
    using namespace std;  
      
      
    const int inf = 0x7f7f7f7f;  
      
      
    struct node  
    {  
        string name;  
        int pa;  
    }nd[N],ans;  
    int n,s,x,y,mod;  
    string name,num,tmp;  
      
    int ToNo(string st)  
    {  
        int no = 0;  
        for (int i = 0; i < st.size(); ++i)  
        {  
            no = no*10 + st[i] - '0';  
        }  
        return no;  
    }  
    int main()  
    {  
    //    Read();  
        int T;  
        scanf("%d",&T);  
        while (T--)  
        {  
            scanf("%d%d%d%d%d",&n,&s,&x,&y,&mod);  
            for (int i = 0; i < n; ++i)  
            {  
                cin>>name>>tmp>>num>>tmp;  
                nd[i].name = name;  
                nd[i].pa = ToNo(num);  
            }  
            int cnt = 0;  
            for (int i = 0; i < n; ++i)  
            {  
                int tp = cnt + nd[i].pa;  
                if (tp <= s)  
                {  
                    cnt += nd[i].pa;  
                    ans = nd[i];  
                }  
                else  
                {  
                    ans.name = nd[i].name;  
                    ans.pa = s - cnt;  
                    cnt = 0;  
                    s = (s*x + y)%mod;  
                    if (s == 0) s = (s*x + y)%mod;  
                    i--;  
                }  
                cout<<ans.pa<<" pages "<<"for "<<ans.name<<endl;  
            }  
            cout<<endl;  
        }  
    }  
    View Code
  • 相关阅读:
    python数据库的增删改查
    Python基础教程笔记——第3章:使用字符串
    Python基础教程笔记——第2章:列表和元组
    Python基础教程笔记——第1章
    指针与数组的对比(——选自:C++内存管理技术内幕)
    C++内存分配方式(——选自:C++内存管理技术内幕)
    C++函数的重载,覆盖和隐藏(——高质量编程第14章)
    vim—基本命令1
    linux命令1——基础
    free delete malloc new(——高品质量程序设计指南第16章)
  • 原文地址:https://www.cnblogs.com/E-star/p/3143237.html
Copyright © 2020-2023  润新知