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 }
最小值
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最大值时用线段树维护即可。
最大值
我觉得略有点神仙啊。。一道题改了一下午。。。大半个下午都在:题解在说啥???它说的是中文???喵喵喵??
倒是码出来(虽然比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 }