zoukankan      html  css  js  c++  java
  • 广大附中2019CSP模拟day6

    Day6

    T1

    大意:维护一个长度$10^5$序列,维护以下操作共$5*10^5$次,保证输入的所有数据随机

    1. 修改某个位置的值
    2. 将某个区间内的所有值$val$变为$100000-val$
    3. 给出$a,b,c$,和一个区间,问区间中$a*i+b*val_i+c*i*val_i$的最大值

    题解:

    • 对于前两个操作可以用线段树维护区间最大值
    • 对于询问操作,我们考虑当存在一个$j>i且val_j>val_i$,那么$i$就没用了,于是我们查出这个区间$val_i$最大的位置,然后就只用考虑位置比$i$大在地方了,重复这个操作,由于数据随机,很随机,我也不知道为什么复杂度是对的,随机说它是对的就对的
      1 #include<bits/stdc++.h>
      2 #define FOR(i,a,b) for (register ll i=(a);i<=(b);i++)
      3 #define For(i,a,b) for (register ll i=(a);i>=(b);i--)
      4 #define mem(i,j) memset(i,j,sizeof(i))
      5 #define GO(u) for (register ll j=f[u];j!=-1;j=nxt[j])
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define pii pair<ll,ll>
     10 #define MP make_pair
     11 using namespace std;
     12 typedef long long ll;
     13 const ll N=1e5+5;
     14 ll n,m,x,y[N],a,b,c,tag[N<<2],ans;
     15 pii zh[N<<2],f[N<<2],tmp;
     16 char opt[10];
     17 inline ll read()
     18 {
     19     ll x=0,f=1;
     20     char c=getchar();
     21     while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
     22     while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
     23     return f*x;
     24 }
     25 inline void write(ll x)
     26 {
     27     if (x<0) putchar('-'),x=-x;
     28     if (x>9) write(x/10);
     29     putchar(x%10+'0');
     30     return;
     31 }
     32 inline ll rd()
     33 {
     34     x=(100000005*x+20150609)%998244353;
     35     return x/100;
     36 }
     37 inline ll rd_pos() {return rd()%n+1;}
     38 inline ll rd_val() {return rd()%100001;}
     39 inline void up(ll p)
     40 {
     41     ll ls=p<<1,rs=p<<1|1;
     42     zh[p]=max(zh[ls],zh[rs]);
     43     f[p]=max(f[ls],f[rs]);
     44     return;
     45 }
     46 inline void bd(ll p,ll l,ll r)
     47 {
     48     if (l==r)
     49     {
     50         zh[p]=MP(y[l],l);
     51         f[p]=MP(100000-y[l],l);
     52         return;
     53     }
     54     ll ls=p<<1,rs=p<<1|1,mid=(l+r)>>1;
     55     bd(ls,l,mid);
     56     bd(rs,mid+1,r);
     57     up(p);
     58     return;
     59 }
     60 inline void down(ll p)
     61 {
     62     ll ls=p<<1,rs=p<<1|1;
     63     if (!tag[p]) return;
     64     swap(zh[ls],f[ls]);
     65     swap(zh[rs],f[rs]);
     66     tag[ls]^=1;
     67     tag[rs]^=1;
     68     tag[p]=0;
     69     return;
     70 }
     71 inline void xg(ll p,ll l,ll r,ll L,ll R)
     72 {
     73     if (L<=l&&r<=R)
     74     {
     75         tag[p]^=1;
     76         swap(zh[p],f[p]);
     77         return;
     78     }
     79     ll ls=p<<1,rs=p<<1|1,mid=(l+r)>>1;
     80     down(p);
     81     if (L<=mid) xg(ls,l,mid,L,R);
     82     if (R>mid) xg(rs,mid+1,r,L,R);
     83     up(p);
     84     return;
     85 }
     86 inline void md(ll p,ll l,ll r,ll k,ll v)
     87 {
     88     if (l==r)
     89     {
     90         zh[p]=MP(v,l);
     91         f[p]=MP(100000-v,l);
     92         return;
     93     }
     94     ll ls=p<<1,rs=p<<1|1,mid=(l+r)>>1;
     95     down(p);
     96     if (k<=mid) md(ls,l,mid,k,v);
     97     else md(rs,mid+1,r,k,v);
     98     up(p);
     99     return;
    100 }
    101 inline pii qr(ll p,ll l,ll r,ll L,ll R)
    102 {
    103     if (L<=l&&r<=R) return zh[p];
    104     ll ls=p<<1,rs=p<<1|1,mid=(l+r)>>1;
    105     pii ret=MP(0,0);
    106     down(p);
    107     if (L<=mid) ret=max(ret,qr(ls,l,mid,L,R));
    108     if (R>mid) ret=max(ret,qr(rs,mid+1,r,L,R));
    109     up(p);
    110     return ret;
    111 }
    112 inline void solve2()
    113 {
    114     bd(1,1,n);
    115     while (m--)
    116     {
    117         scanf("%s",opt+1);
    118         if (opt[1]=='C') 
    119         {
    120             int pos=rd_pos();
    121             md(1,1,n,pos,rd_val());
    122         }
    123         else if (opt[1]=='R')
    124         {
    125             ll l=rd_pos(),r=rd_pos();
    126             if (l>r) swap(l,r);
    127             xg(1,1,n,l,r);
    128         }
    129         else
    130         {
    131             ans=0;
    132             a=read(),b=read(),c=read();
    133             ll l=rd_pos(),r=rd_pos();
    134             if (l>r) swap(l,r);
    135             tmp=MP(0,0);
    136             while (l<=r)
    137             {
    138                 tmp=qr(1,1,n,l,r);
    139                 l=tmp.se+1;
    140                 ans=max(ans,tmp.fi*b+tmp.se*a+tmp.fi*tmp.se*c);
    141             }
    142             write(ans),putchar('
    ');
    143         }
    144     }
    145     return;
    146 }
    147 int main()
    148 {
    149     n=read(),m=read(),x=read();
    150     FOR(i,1,n) y[i]=rd_val();
    151     solve2();
    152     return 0;
    153 }
    View Code

    T2

    大意:给出一个包含$0,1,2$的大小为$500*500$的矩形,问最多可以取出多少个相邻三个组成的拐角,且1是拐点,2是另外两个位置

    题解:

    • 好像这种取出某种特定形状的题目大概都是网络流
    • 对于每个拐角,两个2的位置连边,又考虑到中间的1位置只能被用一次,所以中间再加一个1位置的点并且拆点限流
    • 这个图显然是个二分图,但是哪些2连S,哪些2连T不大清楚,可以黑白直接标号(但是我实现挂了),也可以对行黑白染色,黑色和白色分别连向S和T
      1 #include<bits/stdc++.h>
      2 #define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
      3 #define For(i,a,b) for (register int i=(a);i>=(b);i--)
      4 #define mem(i,j) memset(i,j,sizeof(i))
      5 #define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define pii pair<int,int>
     10 #define MP make_pair
     11 using namespace std;
     12 typedef long long ll;
     13 const int N=500*500*3+5;
     14 const int M=2e6+5;
     15 const int inf=1e8;
     16 int n,m,a[505][505],num[505][505][3];
     17 int tot=1,f[N],nxt[M],vis[N],dep[N],S,T,pt=0,maxflow=0;
     18 int fx[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
     19 queue <int> q;
     20 struct E
     21 {
     22     int u,v,flow;
     23 }e[M];
     24 inline int read()
     25 {
     26     int x=0,f=1;
     27     char c=getchar();
     28     while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
     29     while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
     30     return f*x;
     31 }
     32 inline void write(int x)
     33 {
     34     if (x<0) putchar('-'),x=-x;
     35     if (x>9) write(x/10);
     36     putchar(x%10+'0');
     37     return;
     38 }
     39 inline void add(int u,int v,int flow)
     40 {
     41     tot++;
     42     nxt[tot]=f[u];
     43     f[u]=tot;
     44     e[tot]=(E){u,v,flow};
     45     return;
     46 }
     47 inline void make_edge(int u,int v,int flow)
     48 {
     49     add(u,v,flow);
     50     add(v,u,0);
     51     return;
     52 }
     53 inline int bfs()
     54 {
     55     while (q.size()) q.pop();
     56     FOR(i,0,T) vis[i]=dep[i]=0;
     57     vis[S]=dep[S]=1;
     58     q.push(S);
     59     while (q.size())
     60     {
     61         int u=q.front();
     62         q.pop();
     63         GO(u)
     64         {
     65             int v=e[j].v;
     66             if (!e[j].flow) continue;
     67             if (dep[v]) continue;
     68             dep[v]=dep[u]+1;
     69             q.push(v);
     70             if (dep[T]) return 1;
     71         }
     72     }
     73     return dep[T];
     74 }
     75 inline int Dinic(int u,int fl)
     76 {
     77     if (u==T||!fl) return fl;
     78     int rest=fl,k;
     79     for (register int j=f[u];j!=-1;j=nxt[j])
     80     {
     81         int v=e[j].v;
     82         if (!e[j].flow) continue;
     83         if (dep[v]!=dep[u]+1) continue;
     84         k=Dinic(v,min(rest,e[j].flow));
     85         if (!k)
     86         {
     87             dep[v]=0;
     88             continue;
     89         }
     90         e[j].flow-=k;
     91         e[j^1].flow+=k;
     92         rest-=k;
     93     }
     94     return fl-rest;
     95 }
     96 int main()
     97 {
     98     mem(f,-1);
     99     n=read(),m=read();
    100     FOR(i,1,n) FOR(j,1,m) a[i][j]=read();
    101     FOR(i,1,n) FOR(j,1,m) num[i][j][0]=++pt;
    102     FOR(i,1,n) FOR(j,1,m) num[i][j][1]=++pt;
    103     S=++pt,T=++pt;
    104     FOR(i,1,n) FOR(j,1,m)
    105     {
    106         if (a[i][j]==1) make_edge(num[i][j][0],num[i][j][1],1);
    107         else if (a[i][j]==2)
    108         {
    109             FOR(k,0,3)
    110             {
    111                 int x=i+fx[k][0],y=j+fx[k][1];
    112                 if (x<1||x>n||y<1||y>m) continue;
    113                 if (a[x][y]!=1) continue;
    114                 if (i&1) make_edge(num[i][j][0],num[x][y][0],1);
    115                 else make_edge(num[x][y][1],num[i][j][0],1);
    116             }
    117             if (i&1) make_edge(S,num[i][j][0],1);
    118             else make_edge(num[i][j][0],T,1);
    119         }
    120     }
    121     while (bfs()) 
    122     {
    123         int tmp;
    124         while (tmp=Dinic(S,inf)) maxflow+=tmp;
    125     }
    126     write(maxflow),putchar('
    ');
    127     return 0;
    128 }
    View Code

    T3

    大意:给出$80$个学生以及他们的得分区间,两端点是整数,每个人的得分等概率地取这个区间中的一个实数,回答一个矩阵,即每个人排每个名次的概率

    题解:

    • pb说,显然,要把分数区间离散化,每个人的分数被分成了$O(n)$个区间
    • 我们首先枚举每个人,一个个人处理,再枚举他的一个个得分小区间,逐个处理
    • 设计状态$dp_{i,j,k}$表示处理了这个人和前$i$个人的关系,这前$i$个人中(除了他自己)落在小区间左边的人数为$j$,落在小区间之间的人数为$k$,落在小区间之后的人数为$n-k-j-1$,的概率
    • 转移时算出第$i$个人落在三个部分的概率随便转移即可
    • 如何用$dp$数组求出答案,对于$dp_{i,j,k}$我们显然知道$j$个比我垃圾,$n-j-k-1$个比我强,中间这$k$个人加上我,其实我在这$k$个人中是等概率排名的,于是枚举这个排名即可
    • 时间复杂度$O(n^5)$
     1 #include<bits/stdc++.h>
     2 #define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
     3 #define For(i,a,b) for (register int i=(a);i>=(b);i--)
     4 #define mem(i,j) memset(i,j,sizeof(i))
     5 #define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
     6 #define fi first
     7 #define se second
     8 #define pb push_back
     9 #define pii pair<int,int>
    10 #define MP make_pair
    11 using namespace std;
    12 typedef long long ll;
    13 const int N=201;
    14 int n,l[N],r[N],a[N],len=0;
    15 double dp[N][N][N],ans[N][N];
    16 inline int read()
    17 {
    18     int x=0,f=1;
    19     char c=getchar();
    20     while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    21     while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    22     return f*x;
    23 }
    24 inline void write(int x)
    25 {
    26     if (x<0) putchar('-'),x=-x;
    27     if (x>9) write(x/10);
    28     putchar(x%10+'0');
    29     return;
    30 }
    31 inline double query(int gl,int gr,int L,int R)
    32 {
    33     if (gr<=L||R<=gl) return 0;
    34     double ret=(1.0*min(R,gr)-max(L,gl))/(1.0*(R-L));
    35     return ret;
    36 }
    37 int main()
    38 {
    39     n=read();
    40     FOR(i,1,n) l[i]=read(),r[i]=read(),a[++len]=l[i],a[++len]=r[i];
    41     sort(a+1,a+len+1);
    42     len=unique(a+1,a+len+1)-a-1;
    43     FOR(i,1,n) l[i]=lower_bound(a+1,a+len+1,l[i])-a,r[i]=lower_bound(a+1,a+len+1,r[i])-a;
    44     FOR(p,1,n)
    45     {
    46         FOR(q,l[p]+1,r[p])
    47         {
    48             double sub=1.0*(a[q]-a[q-1])/(1.0*(a[r[p]]-a[l[p]]));
    49             dp[0][0][0]=1;
    50             FOR(i,1,n)
    51             {
    52                 if (i==p)
    53                 {
    54                     For(j,i,0) For(k,i-j,0) dp[i][j][k]=dp[i-1][j][k];
    55                     continue;
    56                 }
    57                 double p1=query(0,a[q-1],a[l[i]],a[r[i]]);
    58                 double p2=query(a[q-1],a[q],a[l[i]],a[r[i]]);
    59                 double p3=query(a[q],a[len],a[l[i]],a[r[i]]);
    60                 For(j,i,0) For(k,i-j,0) dp[i][j][k]=dp[i-1][j][k]*p3+dp[i-1][j-1][k]*p1+dp[i-1][j][k-1]*p2;
    61             }
    62             FOR(j,0,n) For(k,n-1-j,0) FOR(l,0,k) ans[p][n-l-j]+=sub*dp[n][j][k]/(1.0*(k+1));
    63         }
    64     }
    65     FOR(i,1,n)
    66     {
    67         FOR(j,1,n) printf("%.7lf ",ans[i][j]);
    68         putchar('
    ');
    69     }
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    Two sum 两个数相加
    [ACM] hdu 1286 找新朋友(欧拉函数)
    环形队中实现队列的基本运算
    队列的顺序存储结构及其基本运算的实现
    栈的链式存储结构及其基本运算实现
    栈的顺序存储结构及其基本运算实现
    [ACM] hdu 1205 吃糖果(鸽巢原理)
    [ACM] poj 3128 Leonardo's Notebook (置换群,循环节)
    hdu acm 1051 Zipper
    [ACM] poj 2369 Permutations (置换群循环节长度)
  • 原文地址:https://www.cnblogs.com/C-S-X/p/11677140.html
Copyright © 2011-2022 走看看