2019.8.24 TEST

T1 jigsaw

一开始看到这题的时候,这么多区间询问,修改,想到会用某种数据结构来维护,而且每次喊你异或上一次的答案,肯定是强制在线,这时就听到诸如树套树之类的神仙解法,但本sb蒟蒻并不会,就敲了个sb暴力线段树。原想到树套树肯定是本题正解,但实际上本题正解非常的不可思议。

先观察一下,答案都是在4-1000000之间的质数,所以肯定都是奇数,而每次都要异或答案,结果只能为1或2。所以我们可以反过来想,如果opt为奇数,那么肯定答案异或上奇数的最后一位是0,所以可以让操作符异或上2就是答案。反之,opt是偶数时就异或上1。有了这个思路这题分分钟的事情。这下一直处理到最后一个询问。暴力就可以了!

真的巧妙,积累在这里。

//这题思路是真的强!!!
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
int prime[maxn];
int a[maxn],n,m,k;
int last;
int opt,l,r;
int ans[maxn];
int tot;
int vis[maxn];
int isprime[maxn];
int kkk;
bool flag;
void check(int n){
    memset(vis,0,sizeof(vis));
    for(int i=2;i<=n;i++){
        if(!vis[i]){
            vis[i]=i;
            prime[++kkk]=i;
        }
        for(int j=1;j<=kkk;j++){
            if(prime[j]>vis[i]||prime[j]>n/i) break;
            vis[i*prime[j]]=prime[j];
         }
    }
    for(int i=1;i<=kkk;i++) isprime[prime[i]]=true;
}
int main(){
    freopen("jigsaw.in","r",stdin);
    freopen("jigsaw.out","w",stdout);
    scanf("%d%d%d",&n,&k,&m);
    for(register int i=1;i<=n;i++) scanf("%d",&a[i]);
    check(1000000);
    for(register int i=1;i<=m;i++){
        scanf("%d%d%d",&opt,&l,&r);
        if(flag){
            if(opt%2==1) last=opt^2;//因为lastans为4-1000000中的质数都是奇数,二进制末位为1,可以根据这个性质得出答案
            else last=opt^1;
            flag=false;
            printf("%d\n",last);
        }
        l^=last,r^=last,opt^=last;
        if(opt==1) flag=true;
        else a[l]=r;
    }
    if(opt==1){//最后一个询问暴力改
        for(int i=l;i<=r;i++) if(isprime[a[i]]) ans[++tot]=a[i];
        sort(ans+1,ans+1+tot);
        printf("%d\n",ans[k]);
        return 0;
    }
    return 0;
}

T2 T3就不说了,真的是神仙题,先把std放在这里,之后再来填坑.

T2 baritone

题解如下:

从上往下枚举上边界,从下往上枚举下边界。考虑已经统计出上下边界为枚举的包含至少k个点的矩形数,当下边界往上移动时,可能会删除某些点。用按横坐标排序的有序表维护当前上下边界间的点,只有删除点的前k个点和后k个点会影响答案,其它矩形区域依然可行。这样每次只需要从有序表中删除一个点并统计答案,使用链表即可。

复杂度O(n^2*k)

code:

#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <utility>
#include <vector>
#include <iostream>
#include <set>
#include <map>
#include <queue>
#include <functional>
#include <numeric>
#include <iomanip>
#include <string>
#include <sstream>
#include <cmath>
#include <ctime>
using namespace std;

const int xx[4] = {0, 1, 0, -1};
const int yy[4] = {1, 0, -1, 0};
const int maxn = 4000;
int r, c, n, k, len, x[maxn], y[maxn];
int ne[maxn], pr[maxn], val[maxn], tx[maxn];
int que[maxn], to[maxn], f[maxn];
long long ans, sum;
vector <int> ve[maxn];

char getc() {
    char c = getchar();
    while (c <= 32) c = getchar();
    return c;
}

bool cmp(int x, int y) {
    if (que[x] != que[y])
        return que[x] < que[y];
    else
        return f[x] < f[y];
}

void del(int t) {
    ne[pr[t]] = ne[t];
    pr[ne[t]] = pr[t];
    sum -= val[t];
    int x = ne[t], y = ne[t];
    for (int i = 1; i < k; i++)
        y = ne[y];
    for (int i = 1; i <= k + 1; i++) {
        int v = (que[x] - que[pr[x]]) * (r - que[y] + 1);
        sum += v - val[x];
        val[x] = v;
        x = pr[x];
        y = pr[y];
    }
}

int main() {
    freopen("baritone.in", "r", stdin);
    freopen("baritone.out", "w", stdout);
    scanf("%d%d%d%d", &r, &c, &n, &k);
    ans = 0;
    for (int i = 1; i <= n; i++)
        scanf("%d%d", &x[i], &y[i]), ve[y[i]].push_back(i);
    for (int i = 1; i <= c; i++) {
        sum = 0;
        len = 0;
        for (int j = 0; j <= 20; j++)
            que[++len] = 0, que[++len] = r + 1;
        for (int j = 1; j <= n; j++)
            if (y[j] >= i) {
                que[++len] = x[j];
                f[len] = y[j];
                to[j] = len;
            }
        for (int j = 1; j <= len; j++)
            tx[j] = j;
        sort(tx + 1, tx + len + 1, cmp);
        for (int j = 1; j < len; j++)
            ne[tx[j]] = tx[j + 1], pr[tx[j + 1]] = tx[j];
        ne[tx[len]] = tx[len];
        pr[tx[1]] = tx[1];
        for (int j = 1; j <= len; j++) {
            int now = j;
            for (int p = 1; p < k; p++)
                now = ne[now];
            val[j] = (que[j] - que[pr[j]]) * (r - que[now] + 1);
            sum += val[j];
        }
        for (int j = c; j >= i; j--) {
            ans += sum;
            for (int p = 0; p < (int) ve[j].size(); p++)
                del(to[ve[j][p]]);
        }
    }
    cout << ans << endl;
    return 0;
}

T3 coffee

这题更神仙,题解搬运如下:

考虑使用dp解决这个问题。用表示使用i次能力,当前有一罐j种咖啡,期望能喝到多少罐,则

发现dp时会产生环,则记忆化搜索并记录当前项的系数,在发现环后根据当前系数解出环上的dp值。为了输出取模后的值,需要实数dp一次,取模后再dp一次,根据实数dp的结果找到最优解的位置,再输出取模dp的答案即可。

%%%%% code:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cassert>
#include <cmath>
using namespace std;
typedef long long LL;

const int maxn=2010, mod=998244353;
const double eps=1e-12;
int n, k;

LL qpow(LL num, int cnt=mod-2){
    LL back=1;
    for (; cnt; cnt>>=1){
        if (cnt&1)
            back=back*num%mod;
        num=num*num%mod;
    }
    return back;
}

struct Value{
    double val;
    int mval;
    Value (int numerator=-1, int denominator=1){
        mval=qpow(denominator)*numerator%mod;
        val=(double)numerator/denominator;
    }
    inline Value operator * (const Value &an){
        Value back;
        back.val=val*an.val;
        back.mval=(LL)mval*an.mval%mod;
        return back;
    }
    inline Value operator / (const Value &an){
        Value back;
        if (fabs(val)<eps)
            back.val=0;
        else
            back.val=val/an.val;
        back.mval=qpow(an.mval)*mval%mod;
        return back;
    }
    inline Value operator + (const Value &an){
        Value back;
        back.val=val+an.val;
        back.mval=(mval+an.mval)%mod;
        return back;
    }
    inline Value operator - (const Value &an){
        Value back;
        back.val=val-an.val;
        back.mval=(mval-an.mval+mod)%mod;
        return back;
    }
    inline bool valid(){
        return ~mval;
    }
    void read(){
        cin>>val;
        mval=(int)(val*1000+0.5)*qpow(1000)%mod;
    }
};

ostream &operator << (ostream &os, const Value &an){
    os<<an.val<<" / "<<an.mval;
    return os;
}
Value _1=Value(1,1), _0=Value(0,1);
struct state{
    Value k, v;
    state(Value k=_1, Value v=_0):k(k), v(v){}
    state add(Value k2, Value v2){
        return state(k*k2, k*v2+v);
    }
} nil;
class costumStack{
    private:
        state sta[maxn];
        int siz;

    public:
        void push(state an){
            sta[++siz]=an;
        }
        int size(){
            return siz;
        }
        void pop(){
            siz--;
        }
        state top(){
            return sta[siz];
        }
        state get(int pos){
            return sta[pos];
        }
} sta;

Value dp[maxn][maxn];
Value a[maxn];
int b[maxn];
int dep[maxn];
int maxcycle;

Value get(int x, int y, state s=nil, int layer=1){
    while (y>n) y-=n;
    if (dp[x][y].valid())
        return dp[x][y];
    if (dep[y]){
        state tmp=sta.get(dep[y]);
//        cerr<<"["<<x<<","<<y<<", cycle: "<<layer-dep[y]<<"] "<<s.k<<" "<<s.v<<endl;
        maxcycle=max(maxcycle, layer-dep[y]);
        tmp.k=tmp.k-s.k;
        tmp.v=s.v-tmp.v;
        return dp[x][y]=tmp.v/tmp.k;
    }

    dep[y]=layer;
    sta.push(s);
    int tmp=y+b[y]+x;
    Value tmpv=(_1-a[y])*get(x+1, tmp+1)+_1;
    dp[x][y]=a[y]*(get(x, tmp, s.add(a[y], tmpv), layer+1))+tmpv;
    sta.pop();
    dep[y]=0;
    return dp[x][y];
}

int main(){
    freopen("coffee.in", "r", stdin);
    freopen("coffee.out", "w", stdout);
    cin>>n>>k;
    int maxpos=0;
    for (int i=1; i<=n; i++){
        a[i].read();
        if (a[i].val>a[maxpos].val)
            maxpos=i;
    }
    for (int i=1; i<=n; i++)
        cin>>b[i];
    for (int i=1; i<=n; i++)
        dp[k+1][i]=_0;
    for (int i=k; i>=0; i--){
//        cout<<i<<endl;
        for (int j=1; j<=n; j++)
            get(i, j);
    }
//    for (int j=0; j<=k; j++)
//        for (int i=1; i<=n; i++)
//            cerr<<"Case "<<j<<","<<i<<" : "<<dp[j][i]<<endl;
    double mindif=1e20;
    double maxans=0;
    int pos=0;
    for (int i=1; i<=n; i++){
        if (!pos||dp[0][i].val>maxans){
            pos=i;
            mindif=dp[0][i].val-maxans;
            maxans=dp[0][i].val;
        } else {
            mindif=min(mindif, maxans-dp[0][i].val);
        }
    }
/*    cerr<<"Minimum difference is: "<<mindif<<endl;
    cerr<<"Maxpos = "<<maxpos<<", ans = "<<pos<<endl;
    FILE *fres=fopen("res.txt", "w");
    if (mindif<1e-4||k&&maxcycle<(n/10)){
        fprintf(fres, "Invalid");
    } else {
        fprintf(fres, "OK");
    }*/
    printf("%d %d\n", pos, dp[0][pos].mval);
    return 0;
}

复杂度O(n*k)

原文地址:https://www.cnblogs.com/LJB666/p/11405777.html

时间: 2024-11-04 20:09:27

2019.8.24 TEST的相关文章

网络流测试-2019.3.24

网络流专题测试-2019.03.24 24号的考试了,但是一直忘了写,今天来补一补. defuze:http://hzwer.com/6009.html 不想写题面了,直接说怎么做吧. 其实这道题可以直接用最普通的费用流来做,找增广路时把spfa的比较函数改改就行了,但是我没想到. 可以对概率取对数,转成加法再做,就非常简单了. 注意:找增广路时设置一个精度,如果两条路径的差小于精度,就不进行松弛.否则可能会在几条费用极其相似的道路上反复增光导致超时. 1 # include <cstdio>

PAT 甲级 A1042 (2019/01/24)

1 #include <cstdio> 2 const int N = 54; 3 char Color[5] = {'S', 'H', 'C', 'D', 'J'}; 4 int start[N+1], trans[N+1], end[N+1]; 5 int main() { 6 int n; 7 scanf("%d",&n); 8 for(int i = 1; i <= N; i++){ 9 start[i] = i; 10 } 11 for(int i

2019.9.24 网络ip小知识

原文链接:https://blog.csdn.net/faker_wang/article/details/80747407 :https://www.cnblogs.com/wktwj/p/10862618.html 摘抄一些我觉得比较需要知道的东西吧 子网掩码: 子网掩码(subnet mask)又叫网络掩码.地址掩码.子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码. 子网掩码不能单独存在,它必须结合IP地址一起使用.子网掩码只有一个作

梦想MxWeb3D协同设计平台 2019.01.24更新

SDK开发包下载地址:http://www.mxdraw.com/ndetail_10124.html1.  编写快速入门教程2.  重构前端代码,支持一个页面多个三维控件同时加载,或二维和三维同时加载 3.  简化前端代码引用控件,只需一个函数就能动态创建三维控件4. 三维控件绘图区域,与界面UI分离5. 二维增加交互绘图接口6. 导出三维建模函数和三维运算函数提供了使用js开发的调用演示例程7. 增加导出二维图纸.遍历.对象查询.修改.绘图等函数 原文地址:https://www.cnblo

2019.03.24后台站点

1.后台站点和admin.py与模型相关联 在admin.py中添加admin.site.register(Clazz) 2.Python manage.py createsuperuser 3.在setting中修改成中文  'zh-Hans' 'Asia/Shanghai' false 4.修改第一个标题  在apps.py中添加 verbose_name = u'学生应用' 然后在init中添加这个, default_app_config = 'stu.apps.StulConfig' 原

2019.03.24 表单类

Form.form是一种内置的模板吧,它有自己设置的表单样式 可以引用它,但我觉得还是自己写会比较好吧 继承的是forms类了而不是models类了 然后就是表单得验证,也是用了内置得数据库叫做 authenticate,login就是存admin密码的那个 概述 表单既可以在模板页面利用HTML编写,也可以使用Django提供的表单类编写. 相关属性参考官网:https://docs.djangoproject.com/en/1.11/ref/forms/fields/ 实现熟悉的用户登录功能

蒟蒻总结-2019.3.24

草草写完的,写的不太好,望谅解 移动"哨兵棋子" 题面+数据规模 一条数轴有\(N\)个棋子,每个棋子可以占据一个整数位置.\(N\)个棋子目前位于不同的整数位置,现在你想要移动它们以便它们占据N个连续位置(例如,位置\(5,6,7,8\)).当前所有棋子中位置最小或者位置最大的棋子,称为"哨兵棋子".每一次,你只能移动"哨兵棋子".你可以把"哨兵棋子"移动到当前任何未占用的整数位置,前提是在这个新位置该棋子不再是一个&quo

2019.4.24(js)

1. 取得正数和负数的绝对值 Math.abs(7.25) Math.abs(-7.25) 2.利用JS刷新页面方法 https://www.cnblogs.com/Chen-XiaoJun/p/6219880.html 1 //刷新当前窗口 2 window.location.href=window.location.href; 3 window.location.reload; 对于刷新父页面的如下: 1 //刷新父页面 2 window.opener.location.href=windo

2019.4.24 扑克牌旋转练习

效果图: 代码: .div2 { width: 100px; margin: 200px auto; position: relative; } .div2 img{ width: 100px; position: absolute; left: 0; top:0; transform-origin: center top; transition: all 1s; } .div2:hover .img1 { transform: rotate(60deg); } .div2:hover .img

原生JS代码封装(将字符串转换为日期 2019.08.24 )

function string2date(str){ if( hasLetter(str) ) { throw new Error("哥们儿,你写错了!!"); } return new Date(str); } 原文地址:https://www.cnblogs.com/sunyang-001/p/10812830.html