NOI2017
加减就是一段区间赋为0/1,这个位置前面第一个0/1变成1/0
线段树维护就可以了,或许常数足够优秀就能过
否则要压位,30个压1位即可.一开始线段树维护了一段区间最左最右的0/1的位置,各种调都只有70多...
然后去参考了一下别人优秀的代码,线段树维护一段区间是不是全0/全1,然后修改一个位置,找到线段树上的一个叶子,修改,然后从它往上跳,以加为例,如果要进位,就从这个叶子开始递归往上的时候,如果目前还没进成,修改的是一段区间的右区间,看看左边是不是全1,如果不是就进位到左边(对左边这棵树调用修改操作,即在线段树上二分最右的0然后往那一位进1),否则的话就把左边的树整体打上变成全0的标记,继续向上递归
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
13 typedef long long LL;
14 typedef double db;
15 using namespace std;
16 const int N=2000011,bs=30,up=2000007;
17 const LL mxup=((1<<30)-1);
18 int n,t1,t2,t3,RS;
19
20 template<typename T> void read(T &x) {
21 char ch=getchar(); x=0; T f=1;
22 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
23 if(ch=='-') f=-1,ch=getchar();
24 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
25 }
26
27 LL allup[N<<2],allo[N<<2],v[N<<2],lz[N<<2]; //1 :1 2 :0
28 #define lc x<<1
29 #define rc ((x<<1)|1)
30 #define mid ((l+r)>>1)
31 void update(int x,int l,int r) {
32 if(l==r) {
33 allup[x]=(v[l]==mxup);
34 allo[x]=(v[l]==0); return;
35 }
36 allup[x]=(allup[lc]&allup[rc]);
37 allo[x]=(allo[lc]&allo[rc]);
38 }
39
40 void change_it(int x,int l,int r,int f) {
41 if(f==1) allup[x]=1,allo[x]=0;
42 else allo[x]=1,allup[x]=0;
43 if(l==r) v[l]=(f==1)?mxup:0;
44 else lz[x]=f;
45 }
46
47 void down(int x,int l,int r) {
48 if(!lz[x]||l==r) return;
49 change_it(lc,l,mid,lz[x]);
50 change_it(rc,mid+1,r,lz[x]);
51 lz[x]=0; return;
52 }
53
54 void change(int x,int l,int r,int F) {
55 if(l==r) {
56 if(F==1) v[l]--; else v[l]++;
57 update(x,l,r); return;
58 }
59 down(x,l,r);
60 if((F==1&&!allo[lc])||(F==2&&!allup[lc])) change(lc,l,mid,F);
61 else { change_it(lc,l,mid,F); change(rc,mid+1,r,F); }
62 update(x,l,r);
63 }
64
65 void add(int x,int l,int r,int pos,LL V) {
66 if(l==r) {
67 v[l]+=V; RS=0;
68 if(v[l]>mxup) { v[l]-=(mxup+1); RS=2; }
69 else if(v[l]<0) { v[l]+=(mxup+1); RS=1; }
70 update(x,l,r); return;
71 }
72 down(x,l,r);
73 if(pos<=mid) add(lc,l,mid,pos,V);
74 else add(rc,mid+1,r,pos,V);
75 if(RS&&pos<=mid) {
76 if((RS==2&&!allup[rc])||(RS==1&&!allo[rc])) {
77 change(rc,mid+1,r,RS); RS=0;
78 }
79 else change_it(rc,mid+1,r,RS);
80 }
81 update(x,l,r); return;
82 }
83
84 int get_it(int x,int l,int r,int pos,int f) {
85 if(l==r) {
86 return (v[l]&(1LL<<f))!=0;
87 }
88 down(x,l,r);
89 if(pos<=mid) return get_it(lc,l,mid,pos,f);
90 return get_it(rc,mid+1,r,pos,f);
91 }
92
93 void build(int x,int l,int r) {
94 if(l==r) { allo[x]=1; allup[x]=0; return; }
95 build(lc,l,mid); build(rc,mid+1,r);
96 update(x,l,r);
97 }
98
99 //#define DEBUG
100 int main() {
101 #ifdef DEBUG
102 freopen("integer.in","r",stdin);
103 freopen("integer.out","w",stdout);
104 #endif
105 read(n); read(t1); read(t2); read(t3);
106 build(1,1,up);
107 For(ti,1,n) {
108 LL o,k,a,b,f,len=0,tp=1,l,r,ql,qr;
109 read(o);
110 if(o==1) {
111 read(a); read(b);
112 if(a<0) f=-1,a=-a; else f=1;
113 while((tp<<1)<=a) { tp<<=1; len++; }
114 l=b; r=b+len;
115 ql=l/bs+1; qr=r/bs+1;
116 a<<=(l-(ql-1)*bs);
117 if(a&mxup) add(1,1,up,ql,f*(a&mxup));
118 if(a>>bs) add(1,1,up,qr,f*(a>>bs));
119 }
120 else {
121 read(k);
122 printf("%d\n",get_it(1,1,up,k/bs+1,k%bs));
123 }
124 }
125 return 0;
126 }
127 /*
128 9000 3 4 2
129 1 898032183 19097
130 1 899706564 244829
131 1 430516929 109811
132 1 -116763903 87261
133 1 -675576449 63566
134 1 878664431 199539
135 2 97764
136 */
一道卡常数的神题(???)
为什么我改到和llj几乎一模一样都过不了呀,我到底是哪里写得不够优秀呀???luogu上T1个点,bz上过了
hash,考虑没有切开的操作时,发现对于连接的操作,暴力计算横跨连接点的长度小于50的串,每个串只会横跨链接点一次,复杂度就是k*n
对于切除操作,复杂度是k*k*c,连回去还是k*k*c的
所以直接hash就可以了.
大常数选手色色发抖.
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #define For(i,a,b) for(register int i=(a);i<=(b);++i)
12 #define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
13 const int N=3e5+7,bs=13,p1=10233333,p2=998244353;
14 typedef long long LL;
15 typedef unsigned long long uLL;
16 typedef double db;
17 using namespace std;
18 int n,m,v[N];
19 uLL power2[55];
20 char s[N];
21
22 template<typename T> void read(T &x) {
23 char ch=getchar(); x=0; T f=1;
24 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
25 if(ch=='-') f=-1,ch=getchar();
26 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
27 }
28
29 int tot,fir[p1+7],nxt[p1+7],cnt[p1+7];
30 uLL H[p1+7];
31 void add(int H1,uLL H2,int v) {
32 for(int i=fir[H1];i;i=nxt[i]) if(H[i]==H2) {
33 cnt[i]+=v; return;
34 }
35 nxt[++tot]=fir[H1]; fir[H1]=tot; H[tot]=H2; cnt[tot]=v;
36 }
37
38 int qry(int H1,uLL H2) {
39 for(int i=fir[H1];i;i=nxt[i]) if(H[i]==H2) return cnt[i];
40 return 0;
41 }
42
43 int nx[N],pr[N],sta[N],top;
44 void dfspr(int x,int pos) {
45 if(pos<50&&pr[x]) dfspr(pr[x],pos+1);
46 sta[++top]=v[x];
47 }
48
49 void dfsnx(int x,int pos) {
50 sta[++top]=v[x];
51 if(pos<50&&nx[x]) dfsnx(nx[x],pos+1);
52 }
53
54 uLL prH2[N];
55 void pre() {
56 For(i,1,top)
57 prH2[i]=prH2[i-1]*bs+sta[i];
58 }
59
60 void get_H(int l,int r,uLL &H2) {
61 l--;
62 H2=prH2[r]-prH2[l]*power2[r-l];
63 }
64
65 //#define DEBUG
66 int main() {
67 #ifdef DEBUG
68 freopen("queue.in","r",stdin);
69 freopen("queue.out","w",stdout);
70 #endif
71 read(n); read(m);
72 power2[0]=1;
73 For(i,1,55) power2[i]=power2[i-1]*bs;
74 For(i,1,n) { read(v[i]); add(v[i],v[i],1); }
75 For(i,1,m) {
76 int o,x,y,k;
77 read(o);
78 if(o==1) {
79 read(x); read(y); top=0;
80 int ll,rr;
81 dfspr(x,1); ll=top;
82 dfsnx(y,1); rr=top-ll;
83 //pre();
84 For(i,1,ll) {
85 uLL H2=0;
86 For(j,i,ll) H2=H2*bs+sta[j];
87 For(j,1,rr) {
88 //int H1=0; uLL H2=0;
89 //get_H(i,ll+j,H2);
90 H2=H2*bs+sta[ll+j];
91 int H1=H2%p1;
92 add(H1,H2,1);
93 }
94 }
95 nx[x]=y; pr[y]=x;
96 }
97 else if(o==2) {
98 read(x);
99 top=0;
100 int ll,rr;
101 dfspr(x,1); ll=top;
102 dfsnx(nx[x],1); rr=top-ll;
103 /*pre();
104 For(i,1,ll)
105 For(j,1,rr) {
106 int H1=0; uLL H2=0;
107 get_H(i,ll+j,H2);
108 H1=H2%p1;
109 add(H1,H2,-1);
110 } */
111 For(i,1,ll) {
112 uLL H2=0;
113 For(j,i,ll) H2=H2*bs+sta[j];
114 For(j,1,rr) {
115 //int H1=0; uLL H2=0;
116 //get_H(i,ll+j,H2);
117 H2=H2*bs+sta[ll+j];
118 int H1=H2%p1;
119 add(H1,H2,-1);
120 }
121 }
122 pr[nx[x]]=0; nx[x]=0;
123 }
124 else {
125 scanf("%s",s); int len=strlen(s);
126 top=0;
127 For(i,0,len-1) sta[++top]=s[i]-'0';
128 pre();
129 read(k);
130 LL ans=1;
131 For(i,1,len-k+1) {
132 int H1=0; uLL H2=0;
133 get_H(i,i+k-1,H2);
134 H1=H2%p1;
135 ans=ans*qry(H1,H2)%p2;
136 }
137 printf("%lld\n",ans);
138 }
139 }
140 return 0;
141 }
???我不会呀,等着sxy给我讲
-------------------------------4-25upd-----------------------------
ans[k]表示最大子矩阵小于等于k的答案,那么答案就是ans[k]-ans[k-1]
如何计算ans[k]
f[i]表示前i行最大子矩阵小于等于k的概率
ans[k]=f[n]
发现泳池高大于最大的k,即可以看作泳池无限高.
如何求f:
定义g[i][j]表示连续的j列靠泳池边的前i行都是安全的,并且最小子矩阵小于等于k的概率
h[i][j]表示连续的j列靠泳池边的前i行都是安全的,(i+1,j)是危险的,并且最小子矩阵小于等于k的概率
$f[i]=\sum_{j=1}^{min(k,i)}f[i-j]*g[1][j-1]*(1-p)$
这是一个k阶常系数线性齐次递推,可以用多项式取模优化到n^2或nlogklogn
如何求g,h
$g[k][1]=h[k][1]=p^k*(1-p)$
$g[i][0]=h[i][0]=1$
$g[i][j]=\sum_{t=0}^jh[i][t]*g[i+1][j-t]$
$h[i][j]=\sum_{t=0}^{j-1}h[i][t]*g[i+1][j-t-1]*p^i*(1-p)$
$第i行,j<=\lfloor k/i \rfloor,所以求g,h是k^2的$
1 //Achen 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdlib> 6 #include<vector> 7 #include<cstdio> 8 #include<queue> 9 #include<cmath> 10 #include<set> 11 #include<map> 12 const int N=1007,mod=998244353; 13 #define For(i,a,b) for(int i=(a);i<=(b);i++) 14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--) 15 typedef long long LL; 16 typedef double db; 17 using namespace std; 18 LL n,x,y,p,h[N][N],g[N][N],power[N],f[N],A[N]; 19 20 template<typename T> void read(T &x) { 21 char ch=getchar(); x=0; T f=1; 22 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); 23 if(ch=='-') f=-1,ch=getchar(); 24 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f; 25 } 26 27 LL ksm(LL a,LL b) { 28 LL rs=1,bs=a; 29 while(b) { 30 if(b&1) rs=rs*bs%mod; 31 bs=bs*bs%mod; 32 b>>=1; 33 } 34 return rs; 35 } 36 37 LL mo(LL x) { return x>=mod?x-mod:x; } 38 39 LL rs[N<<1],bs[N<<1],c[N<<1]; 40 LL cheng(LL a[],LL b[],int k) { 41 memset(c,0,sizeof(c)); 42 For(i,0,k-1) For(j,0,k-1) 43 c[i+j]=mo(c[i+j]+a[i]*b[j]%mod); 44 Rep(i,2*k-1,k) For(j,1,k) 45 c[i-j]=mo(c[i-j]+A[j]*c[i]%mod); 46 For(i,0,k-1) a[i]=c[i]; 47 } 48 49 void mul(LL b,int k) { 50 rs[0]=1; bs[1]=1; 51 while(b) { 52 if(b&1) cheng(rs,bs,k); 53 cheng(bs,bs,k); 54 b>>=1; 55 } 56 } 57 58 LL solve(LL k) { 59 memset(g,0,sizeof(g)); 60 memset(h,0,sizeof(h)); 61 memset(f,0,sizeof(f)); 62 memset(rs,0,sizeof(rs)); 63 memset(bs,0,sizeof(bs)); 64 g[k][1]=h[k][1]=power[k]*(1-p+mod)%mod; 65 g[k][0]=h[k][0]=1; 66 Rep(i,k-1,1) { 67 g[i][0]=h[i][0]=1; 68 For(j,1,k/i) 69 For(t,0,j) { 70 if(t<=j-1) h[i][j]=mo(h[i][j]+h[i][t]*g[i+1][j-t-1]%mod*power[i]%mod*(1-p+mod)%mod); 71 g[i][j]=mo(g[i][j]+h[i][t]*g[i+1][j-t]%mod); 72 } 73 } 74 f[0]=1; 75 For(i,1,k) { 76 For(j,1,i) 77 f[i]=mo(f[i]+f[i-j]*g[1][j-1]%mod*(1-p+mod)%mod); 78 if(i<=k) f[i]=mo(f[i]+g[1][i]); 79 } 80 if(n<=k) { 81 LL ans=f[n]; 82 return ans; 83 } 84 else { 85 k++; 86 For(i,1,k) A[i]=g[1][i-1]*(1-p+mod)%mod; 87 mul(n,k); LL res=0; 88 For(i,0,k-1) res=mo(res+rs[i]*f[i]%mod); 89 return res; 90 } 91 } 92 93 //#define DEBUG 94 int main() { 95 #ifdef DEBUG 96 freopen("1.in","r",stdin); 97 //freopen(".out","w",stdout); 98 #endif 99 LL k; 100 read(n); read(k); read(x); read(y); 101 p=x*ksm(y,mod-2)%mod; 102 power[0]=1; 103 For(i,1,k) power[i]=power[i-1]*p%mod; 104 LL ans11=solve(k); 105 LL ans22=solve(k-1); 106 LL ans=(ans11-ans22+mod)%mod; 107 printf("%lld\n",ans); 108 return 0; 109 }
---------------------------------------upd---------------------------------一开始f没有加上g[1][i],a只处理到k,还不知道为什么wa....
实际上f的转移是
$f[i]=\sum_{j=1}^{min(k+1,i)}f[i-j]*g[1][j-1]*(1-p)$
本来就是一个k+1阶的递推
怎么是一道2-sat裸题呀
暴力枚举每种x当作a,b,c中的哪一种,然后2-sat判断即可
2-sat板子都写错了...连边都没连对称啊我是个zz吧..
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
13 const int N=400007;
14 typedef long long LL;
15 typedef double db;
16 using namespace std;
17 int n,d,m,no[10],col[N],tid[N][4]; // A:1 B:2 C:3
18 char s[N],ss[10];
19
20 template<typename T> void read(T &x) {
21 char ch=getchar(); x=0; T f=1;
22 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
23 if(ch=='-') f=-1,ch=getchar();
24 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
25 }
26
27 struct node {
28 int a,b,x,y;
29 }q[N];
30
31 int ecnt,fir[N],nxt[N<<1],to[N<<1];
32 void add(int u,int v) {
33 nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
34 }
35
36 int dfs_clock,dfn[N],low[N],bl[N],op[N],tot,sta[N],top;
37 void tarjan(int x) {
38 dfn[x]=low[x]=++dfs_clock;
39 sta[++top]=x;
40 for(int i=fir[x];i;i=nxt[i]) {
41 if(!dfn[to[i]]) {
42 tarjan(to[i]);
43 low[x]=min(low[x],low[to[i]]);
44 }
45 else if(!bl[to[i]]) low[x]=min(low[x],dfn[to[i]]);
46 }
47 if(low[x]==dfn[x]) {
48 tot++;
49 for(;;) {
50 int y=sta[top--];
51 bl[y]=tot;
52 if(y==x) break;
53 }
54 }
55 }
56
57 int fi[N],nx[N],tt[N],ec,in[N];
58 void ADD(int u,int v) {
59 nx[++ec]=fi[u]; fi[u]=ec; tt[ec]=v; in[v]++;
60 }
61
62 queue<int>que;
63 int vis[N];
64 void dfs(int x) {
65 vis[x]=-1;
66 for(int i=fi[x];i;i=nx[i]) if(!vis[tt[i]])
67 dfs(tt[i]);
68 }
69
70 void tpsort() {
71 For(i,1,tot) if(!in[i]) que.push(i);
72 while(!que.empty()) {
73 int x=que.front();
74 que.pop();
75 if(vis[x]) continue;
76 vis[x]=1;
77 dfs(op[x]);
78 for(int i=fi[x];i;i=nx[i]) {
79 in[tt[i]]--;
80 if(!in[tt[i]]) que.push(tt[i]);
81 }
82 }
83 }
84
85 int main() {
86 #ifdef DEBUG
87 freopen(".in","r",stdin);
88 freopen(".out","w",stdout);
89 #endif
90 read(n); read(d);
91 scanf("%s",s+1);
92 read(m);
93 For(i,1,m) {
94 read(q[i].a); scanf("%s",ss); q[i].x=ss[0]-'A'+1;
95 read(q[i].b); scanf("%s",ss); q[i].y=ss[0]-'A'+1;
96 }
97 int up=(3<<d)-1;
98 For(ti,0,up) {
99 For(i,1,n*2) fir[i]=0,dfn[i]=0,bl[i]=0,vis[i]=0;
100 int tp=ti; ecnt=0; tot=0;
101 For(i,1,d) {
102 no[i]=tp%3; tp/=3;
103 }
104 int pos=0;
105 For(i,1,n) {
106 if(s[i]=='x') pos++;
107 if(s[i]=='a'||(s[i]=='x'&&no[pos]==0)) tid[i][1]=0,tid[i][2]=i,tid[i][3]=i+n,col[i]=2,col[i+n]=3;
108 if(s[i]=='b'||(s[i]=='x'&&no[pos]==1)) tid[i][1]=i,tid[i][2]=0,tid[i][3]=i+n,col[i]=1,col[i+n]=3;
109 if(s[i]=='c'||(s[i]=='x'&&no[pos]==2)) tid[i][1]=i,tid[i][2]=i+n,tid[i][3]=0,col[i]=1,col[i+n]=2;
110 }
111 For(i,1,m) {
112 int a=q[i].a,x=q[i].x,b=q[i].b,y=q[i].y;
113 if(a==b&&x==y) continue;
114 if(tid[a][x]) {
115 if(tid[b][y]) {
116 add(tid[a][x],tid[b][y]);
117 int z=tid[a][x]==a?a+n:a;
118 int w=tid[b][y]==b?b+n:b;
119 add(w,z);
120 }
121 else {
122 int z;
123 For(j,1,3) if(tid[a][j]&&j!=x) z=tid[a][j];
124 add(tid[a][x],z);
125 }
126 }
127 }
128 For(i,1,n*2) if(!dfn[i]) tarjan(i);
129 int ok=1;
130 For(i,1,n) {
131 if(bl[i]==bl[i+n]) {
132 ok=0; break;
133 }
134 op[bl[i]]=bl[i+n];
135 op[bl[i+n]]=bl[i];
136 }
137 if(ok) {
138 For(i,1,n*2) {
139 for(int j=fir[i];j;j=nxt[j]) if(bl[to[j]]!=bl[i])
140 ADD(bl[to[j]],bl[i]);
141 }
142 tpsort();
143 For(i,1,n) {
144 if(vis[bl[i]]==1) printf("%c",'A'+col[i]-1);
145 else printf("%c",'A'+col[i+n]-1);
146 }
147 puts("");
148 return 0;
149 }
150 }
151 puts("-1");
152 return 0;
153 }
把每种蔬菜分成两份,最后一个过期的蔬菜单独一份,价值为蔬菜的价值加上额外价值
考虑如果知道了i天的答案,对于i-1天的答案,就是从i的答案中去掉i的答案中买的个数减去i-1天能买的个数那么多个价值最小的蔬菜后的答案
那么只要求出最大的一天的答案就可以了
用堆维护蔬菜价值,每次取出价值最大的,贪心(价值相同与过期天数无关,只要按价值放一定是最优的)地从后往前往可以继续放的天数中放,用并查集维护每一天前面第一个还可以继续放的天数
写的时候总觉得有什么不对劲,写文件名时才发现我给蔬菜的结构题命名为了fruit 2333
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
13 const int N=1e5+7;
14 typedef long long LL;
15 typedef double db;
16 using namespace std;
17 int n,m,k,a[N],s[N],c[N],x[N],canuse[N],cntnow;
18 LL ans[N],ansnow;
19
20 template<typename T> void read(T &x) {
21 char ch=getchar(); x=0; T f=1;
22 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
23 if(ch=='-') f=-1,ch=getchar();
24 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
25 }
26
27 struct Q {
28 int id,ti;
29 friend bool operator <(const Q&A,const Q&B) {
30 return A.ti>B.ti;
31 }
32 }q[N];
33
34 struct ft {
35 int id,ti,cnt;
36 LL val;
37 ft(){}
38 ft(int id,int ti,int cnt,LL val):id(id),ti(ti),cnt(cnt),val(val){}
39 friend bool operator <(const ft&A,const ft&B) {
40 return A.val<B.val;
41 }
42 }f[N];
43
44 int fa[N];
45 int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); }
46
47 priority_queue<ft>que;
48
49 struct node {
50 LL val;
51 node(){}
52 node(LL val):val(val){}
53 friend bool operator <(const node&A,const node&B) {
54 return A.val>B.val;
55 }
56 };
57
58 priority_queue<node>qu;
59
60 void solve(int days) {
61 For(i,1,n) {
62 int tp=x[i]?c[i]/x[i]:days;
63 if(x[i]&&c[i]%x[i]) tp++;
64 que.push(ft(i,tp,1,s[i]+a[i]));
65 tp=x[i]?(c[i]-1)/x[i]:days;
66 if(x[i]&&(c[i]-1)%x[i]) tp++;
67 que.push(ft(i,0,c[i]-1,a[i]));
68 }
69 For(i,1,days) fa[i]=i,canuse[i]=m;
70 for(;;) {
71 if(find(days)==0||que.empty()) break;
72 ft tp=que.top();
73 que.pop();
74 Rep(i,tp.cnt,1) {
75 int ti=x[tp.id]?i/x[tp.id]:days;
76 if(!tp.ti&&x[tp.id]&&i%x[tp.id]) ti++;
77 if(tp.ti) ti=tp.ti;
78 int y=find(min(days,ti));
79 if(y!=0) {
80 canuse[y]--;
81 if(!canuse[y]) { fa[y]=find(fa[y-1]); }
82 qu.push(node(tp.val));
83 ansnow+=tp.val;
84 cntnow++;
85 }
86 else break;
87 }
88 }
89 }
90
91 void work() {
92 ans[q[1].id]=ansnow;
93 For(i,2,k) {
94 int cc=max(0,cntnow-(q[i].ti*m));
95 For(j,1,cc) {
96 node x=qu.top();
97 qu.pop();
98 ansnow-=x.val;
99 cntnow--;
100 }
101 ans[q[i].id]=ansnow;
102 }
103 }
104
105 //#define DEBUG
106 int main() {
107 #ifdef DEBUG
108 freopen("vegetable.in","r",stdin);
109 freopen("vegetable.out","w",stdout);
110 #endif
111 read(n); read(m); read(k);
112 For(i,1,n) {
113 read(a[i]); read(s[i]);
114 read(c[i]); read(x[i]);
115 }
116 For(i,1,k) {
117 read(q[i].ti);
118 q[i].id=i;
119 }
120 sort(q+1,q+k+1);
121 solve(q[1].ti);
122 work();
123 For(i,1,k) printf("%lld\n",ans[i]);
124 return 0;
125 }
什么神仙题,不会