zoukankan      html  css  js  c++  java
  • Problem C: 多线程 解题报告

    Problem C: 多线程

    Description

    多线程是一种常见的加速手段,利用多个线程同时处理不同的任务可以一定程度上减少总耗时,达到提高效率的目的。然而,多个线程间的执行顺序是完全不可控的,这常常会导致一些意料之外的问题。

    一个简单的例子,如果三个线程分别输出A,B,C, 你同时启动这三个线程,最终的输出可能是ACB也可能是CBA等等。更极端的例子,如果两个线程分别输出AB和ab,你甚至可能看到类似AaBb和aABb的输出。

    当你拿到一串输出而他们属于多个线程的时候,反推出每个线程的输出是一件非常麻烦的事情(甚至有时候完全不可能),很不幸,接下来你的任务就是这样一件麻烦事。

    【题意描述】

    现在有两个线程同时在输出数列,线程A输出一个单调递增数列,而线程B输出一个单调递减数列。

    距离来说,如果线程A输出的是11,33,55,而线程B输出的是44,22,那么你可能看到以下的结果:

    11 33 55 44 22

    44 22 11 33 55

    11 44 33 22 55

    ......

    我们假设单个数的输出是不会被打断的(这个性质往往称为“原子操作”),你不必担心两个数被同时输出从而混合成一个新的数。换言之,如果A输出x个数而B输出y个数,你最后一定会得到这x+y个数,只是顺序不确定。

    特别的,某个线程的输出可能是空,你需要考虑到这一点。

    现在你得到了最终的输出,你需要反推出哪些数来自于线程A而哪些数来自于线程B。由于可能有多种情况,我们只要求你输出方案数对1000000007取模的结果。

    Input

    第一行一个正整数T,表示测试数据组数。

    接下来T行,每行描述一组测试数据:

    第一个整数n,表示最终的输出包含n个整数

    接下来n个整数ci,表示最终的输出。

    这些整数两两不同。

    Output

    共T行,每行一个整数,表示可能的情况数。
    特别的,如果无解,你需要输出一个0。

    HINT

    对于100%的数据,1<=T<=10。
    对于20%的数据,n<=20。
    对于50%的数据,n<=1000。
    对于80%的数据,n<=50000。
    对于100%的数据,0<=n<=500000。
    对于100%的数据,ci的绝对值不超过2000000000,且同一组数据内ci两两不同。


    正解在我这种菜的人来说简直不可做,我大概也说不清楚...

    谈一下想法好了。这种类型的题本质是在挖掘状态中间的特殊性,就像莫名其妙看出这个是凸的一样,这个题可以发现一些状态在区间上连续,一些转移在值域上单调,然后通过势能均摊分析,可以得到非常玄妙的复杂度。这种题现在我反正是做不来的,就慢慢见识见识吧。


    Code:

    #include <cstdio>
    const int N=5e5+10;
    const int inf=0x7fffffff,mod=1e9+7;
    struct node
    {
        int val,cnt;
        node(){}
        node(int val,int cnt){this->val=val,this->cnt=cnt;}
    }s0[N],s1[N];
    int T,n,a[N],tot0,tot1;
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            int sum0=1,sum1=1;
            scanf("%d",&n);
            if(!n) {puts("1");continue;}
            for(int i=1;i<=n;i++) scanf("%d",a+i);
            s0[tot0=0]=node(inf,1);//增
            s1[tot1=0]=node(-inf,1);
            for(int i=2;i<=n;i++)
                if(a[i]>a[i-1])//得把那个s1推了
                {
                    int t0=a[i]>s1[0].val?s1[0].cnt:0;
                    int t1=a[i]<s0[0].val?s0[0].cnt:0;
                    while(tot1) (t0+=a[i]>s1[tot1].val?s1[tot1].cnt:0)%=mod,--tot1;
                    s0[++tot0]=node(a[i-1],t0);
                    s1[tot1=0]=node(a[i-1],t1);
                    (sum0+=t0)%=mod,sum1=t1;
                }
                else
                {
                    int t0=a[i]>s1[0].val?s1[0].cnt:0;
                    int t1=a[i]<s0[0].val?s0[0].cnt:0;
                    while(tot0) (t1+=a[i]<s0[tot0].val?s0[tot0].cnt:0)%=mod,--tot0;
                    s0[tot0=0]=node(a[i-1],t0);
                    s1[++tot1]=node(a[i-1],t1);
                    sum0=t0,(sum1+=t1)%=mod;
                }
            printf("%d
    ",(sum0+sum1)%mod);
        }
        return 0;
    }
    

    2019.1.1

  • 相关阅读:
    关于格林尼治时间(GMT)和DateTime相互转换的分享
    Mybatis多表操作
    Mybatis动态SQL
    Mybatis连接池及事务
    Mybatis基本使用
    Mybatis基本入门搭建
    面试刷题29:mysql事务隔离实现原理?
    面试刷题28:如何写出安全的java代码?
    面试刷题27:程序员如何防护java界的新冠肺炎?
    面试刷题26:新冠攻击人类?什么攻击java平台?
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10204322.html
Copyright © 2011-2022 走看看