T1
线段树优化建图后强联通缩点再跑个拓扑排序求一个是否必要即可
用堆维护一下分量内的值
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define pii pair<int,int>
#define fi first
#define bg begin
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?res:-res;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int N=100005,M=600005;
char xxx;
int adj[M],nxt[M<<1],to[M<<1],ecnt;
inline void addedge(int u,int v){
nxt[++ecnt]=adj[u],adj[u]=ecnt,to[ecnt]=v;
}
int n,m,tot;
struct node{
int p,r,c,id;
friend inline bool operator <(cs node &a,cs node &b){
return a.p<b.p;
}
}p[N];
namespace Seg{
int id[M];
#define lc (u<<1)
#define rc ((u<<1)|1)
#define mid ((l+r)>>1)
void build(int u,int l,int r){
id[u]=++tot;
if(l==r){addedge(id[u],l);return;}
build(lc,l,mid),build(rc,mid+1,r);
addedge(id[u],id[lc]),addedge(id[u],id[rc]);
}
void link(int u,int l,int r,int st,int des,int k){
if(st<=l&&r<=des)return addedge(k,id[u]);
if(st<=mid)link(lc,l,mid,st,des,k);
if(mid<des)link(rc,mid+1,r,st,des,k);
}
#undef lc
#undef rc
#undef mid
}
int ps[N],tp[N];
int tim,belnum,bel[M],dfn[M],low[M],stk[M],top,vis[M],d[M],is_t[M],cov[M];
vector<int> E[M];
inline void topsort(){
queue<int> q;
for(int i=1;i<=belnum;i++)if(!d[i])q.push(i);
while(q.size()){
int u=q.front();q.pop();
for(int i=0;i<E[u].size();i++){
int v=E[u][i];
cov[v]|=is_t[u]|cov[u];
d[v]--;if(!d[v])q.push(v);
}
}
}
void tarjan(int u){
dfn[u]=low[u]=++tim,vis[u]=1,stk[++top]=u;
for(int v,e=adj[u];e;e=nxt[e]){
v=to[e];
if(!dfn[v])tarjan(v),chemn(low[u],low[v]);
else if(vis[v])chemn(low[u],dfn[v]);
}
if(low[u]>=dfn[u]){
int tmp;belnum++;
do{
tmp=stk[top--],vis[tmp]=0;
bel[tmp]=belnum,is_t[belnum]|=tmp<=n;
}while(tmp!=u);
}
}
int trp[M],numb;
struct heap{
priority_queue<int,vector<int>,greater<int> >a,b;
inline void push(int x){a.push(x);}
inline void erase(int x){b.push(x);}
inline int size(){return a.size()-b.size();}
inline int top(){
while(b.size()&&a.top()==b.top())a.pop(),b.pop();
return a.top();
}
}qr[N];
char yyy;
int main(){
tot=n=read();
for(int i=1;i<=n;i++){
p[i].p=read(),p[i].r=read(),p[i].c=read(),p[i].id=i;
}sort(p+1,p+n+1);
for(int i=1;i<=n;i++)tp[p[i].id]=i,ps[i]=p[i].p;
Seg::build(1,1,n);
for(int i=1;i<=n;i++){
int l=lower_bound(ps+1,ps+n+1,p[i].p-p[i].r)-ps,
r=upper_bound(ps+1,ps+n+1,p[i].p+p[i].r)-ps-1;
Seg::link(1,1,n,l,r,i);
}
for(int i=1;i<=tot;i++)if(!dfn[i])tarjan(i);
for(int i=1;i<=tot;i++)
for(int j,e=adj[i];e;e=nxt[e]){
j=to[e];
if(bel[i]!=bel[j]){
E[bel[i]].pb(bel[j]);d[bel[j]]++;
}
}ll ans=0;
topsort();
for(int i=1;i<=belnum;i++)if(!cov[i]&&is_t[i])trp[i]=++numb;
for(int i=1;i<=n;i++)if(trp[bel[i]])qr[trp[bel[i]]].push(p[i].c);
for(int i=1;i<=numb;i++){
if(qr[i].size())ans+=qr[i].top();
}
m=read();
while(m--){
int u=tp[read()],id=trp[bel[u]],k=read();
if(cov[bel[u]]){
p[u].c=k;
cout<<ans<<'\n';
continue;
}
ans-=qr[id].top();
qr[id].erase(p[u].c),p[u].c=k;
qr[id].push(p[u].c);
ans+=qr[id].top();
cout<<ans<<'\n';
}
return 0;
}
T2:
利用回文串
l
o
g
log
log个等差数列的形式
然后
e
x
g
c
d
exgcd
exgcd算解的个数
由于每次最多只有
O
(
l
o
g
)
O(log)
O(log)个有交
所以复杂度是两个
l
o
g
log
log的
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define pii pair<int,int>
#define fi first
#define bg begin
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?res:-res;
}
inline int readstring(char *s){
int top=0;char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch))s[++top]=ch,ch=gc();
s[top+1]='\0';return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int N=100005;
char xxx;
struct node{
int s,t,del;
node(int a=0,int b=0,int c=0):s(a),t(b),del(c){}
}p[N][2][61];
int n,m,cnt[N][2];
char str[N];
struct Pam{
int tot,cnt,nxt[N][27],fail[N],len[N],del[N],top[N],s[N],last;
inline void init(){
tot=1,fail[0]=1,len[1]=-1,s[0]=-1;
}
inline int find(int p,int k){
while(s[k-len[p]-1]!=s[k])p=fail[p];return p;
}
inline void insert(int c,node *pt,int &ct){
s[++cnt]=c;int p=find(last,cnt);
if(!nxt[p][c]){
fail[++tot]=nxt[find(fail[p],cnt)][c];
nxt[p][c]=tot,len[tot]=len[p]+2;
del[tot]=len[tot]-len[fail[tot]];
if(del[tot]==del[fail[tot]])top[tot]=top[fail[tot]];
else top[tot]=tot;
}last=nxt[p][c];
p=last;
while(p>1){
pt[++ct]=node(len[top[p]],len[p],del[p]),p=fail[top[p]];
}
}
}t1,t2;
char yyy;
inline int exgcd(int a,int b,int &x,int &y){
if(b==0){x=1,y=0;return a;}
int t=exgcd(b,a%b,y,x);
y-=a/b*x;return t;
}
inline int solve(int a,int b,int la,int lb,int k){
int x,y;int d=exgcd(a,b,x,y);
if(k%d!=0)return 0;
x*=k/d,y*=k/d;
int db=b/d,da=a/d,mx=x%db;if(mx<0)mx+=db;
y+=((x-mx)/db)*da;x=mx;
if(y<0)return 0;
if(y>lb){
int ti=(y-lb-1)/da+1;
y-=ti*da,x+=ti*db;
}
if(x>la||x<0||y>lb||y<0)return 0;
int tt=min((la-x)/db+1,y/da+1);
return tt;
}
inline int check(cs node &x,cs node &y,int len){
return solve(x.del,y.del,(x.t-x.s)/x.del,(y.t-y.s)/y.del,len-x.s-y.s);
}
inline int query(node *l,int a,node *r,int b,int len){
int res=0;
for(int i=a;i&&l[i].s<=len;i--)
for(int j=b;j&&r[j].s+l[a].s<=len;j--)
if(l[i].t+r[j].t>=len)res+=check(l[i],r[j],len);
return res;
}
int main(){
n=read(),m=read();
readstring(str);t1.init(),t2.init();
for(int i=1;i<=n;i++)t1.insert(str[i]-'a',p[i][0],cnt[i][0]);
for(int i=n;i>=1;i--)t2.insert(str[i]-'a',p[i][1],cnt[i][1]);
while(m--){
//cout<<m<<'\n';
int l=read(),r=read();
cout<<query(p[l][1],cnt[l][1],p[r][0],cnt[r][0],r-l+1)<<'\n';
}return 0;
}
T3:
设
f
,
g
[
i
]
[
j
]
[
k
]
f,g[i][j][k]
f,g[i][j][k]表示前
i
i
i行,选了
j
j
j块,删了
k
k
k个位置,当前行选/没选的最大值
考虑转移就相当于是
F
k
=
max
x
(
G
x
+
P
k
−
x
)
F_k=\max_x(G_x+P_{k-x})
Fk=maxx(Gx+Pk−x)这样的东西
而且
P
P
P是一个上凸壳的
那么如果某个时候
G
中
,
i
<
j
,
j
G中,i<j,j
G中,i<j,j比
i
i
i优,以后一定都优,因为
P
P
P递增的越来越慢
于是分治优化决策单调性 D P DP DP即可
http://192.168.110.251/problempage.php?problem_id=4917
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define pii pair<int,int>
#define fi first
#define bg begin
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?res:-res;
}
inline int readstring(char *s){
int top=0;char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch))s[++top]=ch,ch=gc();
s[top+1]='\0';return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int N=10005;
cs ll INF=-9187201950435737472;
ll f[2][4][N],g[2][4][N],p[N],tmp[N],*tg,*tp;
int n,m,A,B,a[N];
void DP(int l,int r,int ql,int qr){
if(l>r)return;
int mid=(l+r)>>1,ps=ql;
ll mx=INF;
for(int i=ql;i<=qr&&i<=mid;i++){
ll vl=tg[i];
if(mid-i<=m)vl+=tp[mid-i];
if(vl>mx)mx=vl,ps=i;
}
chemx(tmp[mid],mx);
DP(l,mid-1,ql,ps);
DP(mid+1,r,ps,qr);
}
inline void trans(ll *ans,ll *_g,ll *_p){
tg=_g,tp=_p;
memset(tmp,128,sizeof(tmp));
DP(0,A,0,A);
for(int i=0;i<=A;i++)chemx(ans[i],tmp[i]);
}
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=read(),m=read(),A=read(),B=read();
memset(f[0],128,sizeof(f[0]));
memset(g[0],128,sizeof(g[0]));
g[0][0][0]=0;
int cur=0;
for(int tt=1;tt<=n;tt++){
p[0]=0;cur^=1;
memset(f[cur],128,sizeof(f[cur]));
memset(g[cur],128,sizeof(g[cur]));
for(int i=1;i<=m;i++)a[i]=read(),p[0]+=a[i];
sort(a+1,a+m+1);
for(int i=1;i<=m;i++)p[i]=p[i-1]-a[i];
for(int j=0;j<=B;j++)
for(int k=0;k<=A;k++)g[cur][j][k]=max(f[cur^1][j][k],g[cur^1][j][k]);
for(int i=0;i<=B;i++)trans(f[cur][i],f[cur^1][i],p);
for(int i=1;i<=B;i++)trans(f[cur][i],g[cur^1][i-1],p);
}ll res=INF;
for(int i=0;i<=B;i++)
for(int j=0;j<=A;j++)chemx(res,max(f[cur][i][j],g[cur][i][j]));
cout<<res<<'\n';return 0;
}