NOIp2018集训test-10-22 (联考六day2)

中间值

两个log肯定会被卡。我用的第一种做法,就是要各种特判要在两个序列都要二分比较麻烦。

 1 //Achen
 2 #include<bits/stdc++.h>
 3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 5 #define Formylove return 0
 6 const int N=1e6+7;
 7 typedef long long LL;
 8 typedef double db;
 9 using namespace std;
10 int n,m,a[N],b[N];
11 
12 template<typename T> void read(T &x) {
13     char ch=getchar(); x=0; T f=1;
14     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
15     if(ch=='-') f=-1,ch=getchar();
16     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
17 }
18 
19 #define ANS
20 int main() {
21 #ifdef ANS
22     freopen("median.in","r",stdin);
23     freopen("median.out","w",stdout);
24 #endif
25     read(n); read(m);
26     For(i,1,n) read(a[i]);
27     For(i,1,n) read(b[i]);
28     For(cs,1,m) {
29         int o,x,y,z,l1,r1,l2,r2;
30         read(o);
31         if(o==1) {
32             read(x); read(y); read(z);
33             if(!x) a[y]=z;
34             else b[y]=z;
35         }
36         else {
37             read(l1); read(r1);
38             read(l2); read(r2);
39             int len=r1-l1+1+r2-l2+1;
40             int tot=len/2+1;
41             int l=1,r=min(tot,r1-l1+1),rs=-1;
42             while(l<=r) {
43                 int mid=((l+r)>>1);
44                 int cnt=tot-mid;
45                 if(cnt>r2-l2+1) l=mid+1;
46                 else {
47                     if((cnt==0||b[l2+cnt-1]<=a[l1+mid-1])&&(l2+cnt>r2||b[l2+cnt]>=a[l1+mid-1])) {
48                         rs=a[l1+mid-1]; break;
49                     }
50                     if(cnt!=0&&b[l2+cnt-1]>a[l1+mid-1]) l=mid+1;
51                     else r=mid-1;
52                 }
53             }
54             if(rs==-1) {
55                 swap(l1,l2); swap(r1,r2);
56                 l=1,r=min(tot,r1-l1+1),rs=-1;
57                 while(l<=r) {
58                     int mid=((l+r)>>1);
59                     int cnt=tot-mid;
60                     if(cnt>r2-l2+1) l=mid+1;
61                     else {
62                         if((cnt==0||a[l2+cnt-1]<=b[l1+mid-1])&&(l2+cnt>r2||a[l2+cnt]>=b[l1+mid-1])) {
63                             rs=b[l1+mid-1]; break;
64                         }
65                         if(cnt!=0&&a[l2+cnt-1]>b[l1+mid-1]) l=mid+1;
66                         else r=mid-1;
67                     }
68                 }
69             }
70             printf("%d\n",rs);
71         }
72     }
73     Formylove;
74 }
View Code

 

 

最小值

dp[i]表示以前i个已经区间分割好了的答案。新加入一个i+1,设i-1前面第一个不大于它的位置为j。

要么i+1单独分割一个区间,这个区间的左端点可以选择从j+1~i+1,从这一段中选择一个pos使dp[pos-1]最大,用dp[pos-1]+f(a[i+1])来更新dp[i+1]

要么i+1和之前的一个数为一个区间,那么这个区间的左端点一定在j或者j之前,也就是i+1没有贡献,直接用dp[j]更新dp[i+1]

我前面不大于我的第一个数用单调栈维护,求dp最大值时用线段树维护即可。

View Code

 

 

最大值

我觉得略有点神仙啊。。一道题改了一下午。。。大半个下午都在:题解在说啥???它说的是中文???喵喵喵??

倒是码出来(虽然比std长了一倍)就直接过了,比较开心。

题解翻译:

$E(x)=\sum_{i=1}^\infty P(x=i)*i$

$E(x)=\sum_{i=1}^\infty P(x \geq i)$

$Ans(l,r)=\sum_{x=1}^\infty P((Max_{i=l}^r v_i) \geq x)$

$\because Max_{i=l}^r v_i=y_1/y_2/y_3……y_m$

$\therefore \forall x\in (y_{i-1}+1,y_i)\ \ P((Max_{i=l}^r v_i) \geq x)=P((Max_{i=l}^r v_i) \geq y_i)$

$\therefore Ans=\sum_{x=1}^m (y_x-y_{x-1})*P((Max_{i=l}^r v_i) \geq y_x)$

$P((Max_{i=l}^r v_i) \geq x)=1-P((Max_{i=l}^r v_i) < x)=1-\prod_{i=l}^rP(v_i<x)$

$=1-\prod_{i=l}^r(1-P(v_i\geq x))$

$\therefore Ans=\sum_{x=1}^m (y_x-y_{x-1})*[1-\prod_{i=l}^r(1-P(v_i\geq y_x))]$

当x从x变到x+1时,只有i中包含能量为$y_{x+1}$的魔法石的i的$P(v_i\geq y_x)$会发生改变,故x从1~m改变总次数为魔法石的总个数。
又因为询问区间互相不包含,把询问区间的(l,r)按l排序,包含i的(l,r)一定是一段连续的区间,那么用线段树维护对于当前的x,每个询问区间的$\prod_{i=l}^r(1-P(v_i\geq y_x))$
每次维护区间乘一个数的操作,因为$1-P(v_i\geq y_x)$会变成0,$y_x$要按从大到小枚举

  1 //Achen
  2 #include<bits/stdc++.h>
  3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
  4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
  5 #define Formylove return 0
  6 const int N=2e5+7,mod=1e9+7;
  7 typedef long long LL;
  8 typedef double db;
  9 using namespace std;
 10 int n,m,q,ls[N],sz;
 11 LL ans,now[N];
 12 
 13 template<typename T> void read(T &x) {
 14     char ch=getchar(); x=0; T f=1;
 15     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 16     if(ch=='-') f=-1,ch=getchar();
 17     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 18 }
 19 
 20 LL ksm(LL a,LL b) {
 21     LL rs=1,bs=a%mod;
 22     while(b) {
 23         if(b&1) rs=rs*bs%mod;
 24         bs=bs*bs%mod;
 25         b>>=1;
 26     }
 27     return rs;
 28 }
 29 
 30 struct stone {
 31     int y,p;
 32     friend bool operator <(const stone &A,const stone &B) {
 33         return A.y<B.y;
 34     }
 35     stone(int y,int p):y(y),p(p){}
 36 };
 37 vector<stone>vc[N];
 38 
 39 struct node {
 40     int i,p;
 41     node(int i,int p):i(i),p(p){}
 42 };
 43 vector<node>v2[N];
 44 
 45 struct sgtree { 
 46     LL sg[N<<2],lz[N<<2];
 47     #define lc (x<<1)
 48     #define rc ((x<<1)|1)
 49     #define mid ((l+r)>>1)
 50     void down(int x,int l,int r) {
 51         if(lz[x]==1) return;
 52         sg[lc]=sg[lc]*lz[x]%mod; lz[lc]=lz[lc]*lz[x]%mod;
 53         sg[rc]=sg[rc]*lz[x]%mod; lz[rc]=lz[rc]*lz[x]%mod;
 54         lz[x]=1;
 55     }
 56     
 57     void build(int x,int l,int r) {
 58         lz[x]=1;
 59         if(l==r) { sg[x]=1LL; return; }
 60         build(lc,l,mid); build(rc,mid+1,r);
 61         sg[x]=(sg[lc]+sg[rc])%mod;
 62     }
 63     
 64     void upd(int x,int l,int r,int ql,int qr,LL v) {
 65         if(l>=ql&&r<=qr) {
 66             sg[x]=sg[x]*v%mod; lz[x]=lz[x]*v%mod; return;
 67         }
 68         down(x,l,r);
 69         if(ql<=mid) upd(lc,l,mid,ql,qr,v);
 70         if(qr>mid) upd(rc,mid+1,r,ql,qr,v);
 71         sg[x]=(sg[lc]+sg[rc])%mod;
 72     }
 73 }T;
 74 
 75 int opl[N],opr[N],qql[N],qqr[N];
 76 
 77 #define ANS
 78 int main() {
 79 #ifdef ANS
 80     freopen("max.in","r",stdin);
 81     freopen("max.out","w",stdout);
 82 #endif
 83     read(n); read(m); read(q);
 84     For(i,1,m) {
 85         int x,y,p;
 86         read(x); read(y); read(p);
 87         vc[x].push_back(stone(y,p));
 88         ls[++ls[0]]=y;
 89     }
 90     int nl=1,nowp=1;
 91     For(i,1,q) {
 92         read(qql[i]); read(qqr[i]);
 93         while(qql[i]>nowp) {
 94             while(nl<i&&qqr[nl]<nowp) nl++;
 95             opl[nowp]=nl; opr[nowp]=i-1;
 96             nowp++;
 97         }
 98         while(nl<i&&qqr[nl]<nowp) nl++;
 99         opl[nowp]=nl; opr[nowp]=i;
100     }
101     while(nowp<=n) {
102         while(nl<=q&&qqr[nl]<nowp) nl++;
103         opl[nowp]=nl; opr[nowp]=q; nowp++;
104     }
105     
106     sort(ls+1,ls+ls[0]+1);
107     sz=unique(ls+1,ls+ls[0]+1)-(ls+1);
108     For(i,1,n) sort(vc[i].begin(),vc[i].end());
109     For(i,1,n) {
110         int up=vc[i].size();
111         LL pr=1,tp=1;
112         For(j,0,up-1) tp=(1LL-vc[i][j].p+mod)%mod*tp%mod;
113         For(j,0,up-1) {
114             LL px=(pr-tp+mod)%mod;
115             pr=(1LL-vc[i][j].p+mod)%mod*pr%mod;
116             int y=lower_bound(ls+1,ls+sz+1,vc[i][j].y)-ls;
117             v2[y].push_back(node(i,px));
118         }
119     }
120     
121     For(i,1,n) now[i]=1;
122     T.build(1,1,q);
123     ls[0]=0;
124     Rep(x,sz,1) {
125         LL tpp=(ls[x]%mod-ls[x-1]%mod+mod)%mod;
126         int up=v2[x].size();
127         For(i,0,up-1) {
128             int pos=v2[x][i].i,tp=(1LL-v2[x][i].p+mod)%mod;
129             if(now[pos]==0) continue;
130             if(opl[pos]&&opl[pos]<=opr[pos]) {
131                 T.upd(1,1,q,opl[pos],opr[pos],tp*ksm(now[pos],mod-2)%mod);
132                 now[pos]=tp;
133             }
134         }
135         ans=(ans+(q-T.sg[1]+mod)%mod*tpp%mod)%mod;
136     }
137     printf("%lld\n",ans);
138     Formylove;
139 }
View Code

 

转载于:https://www.cnblogs.com/Achenchen/p/9831782.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值