最近写了挺多双重有序的题目,所以把题目和代码发上来,就当模板参考吧。
正相关
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 100010;
struct Node
{
ll p,v,d;
Node(ll p=0,ll v=0,ll d=0):p(p),v(v),d(d){}
bool operator < (const Node& rhs) const
{
if(v!=rhs.v) return v<rhs.v;
else if(d!=rhs.d) return d<rhs.d;
else return p<rhs.p;
}
};
ll N,L;
ll a[maxn];
ll ok[maxn];
Node q[maxn];
ll l;
void solve()
{
scanf("%lld %lld",&N,&L);
for(ll i=1;i<=N;i++) scanf("%lld",a+i);
set<Node>s;
l=1;
for(ll i=1;i<=N;i++)
{
while(i-l>L)
{
if(s.count(q[l])) s.erase(q[l]);
l++;
}
set<Node>::iterator it=s.upper_bound(Node(i-L,a[i],0));
if(s.size()==0||it==s.begin())
{
q[i]=Node();
if(i>L) ok[i]=0;
else
{
q[i]=Node(i,a[i],a[i]*a[i]);
s.insert(q[i]);
ok[i]=1;
}
continue;
}
else
{
--it;
Node now=Node(i,a[i],it->d+a[i]*a[i]-it->v);
it=s.upper_bound(now);
if(it!=s.begin()&&(--it)->d>=now.d) continue;
it=s.upper_bound(now);
while(it!=s.end()&&it->d<=now.d) s.erase(it++);
s.insert(now);
q[i]=now;
ok[i]=1;
}
}
if(ok[N]) printf("%lld\n",q[N].d);
else puts("No solution");
}
int main()
{
ll T;
scanf("%lld",&T);
for(ll t=1;t<=T;t++)
{
printf("Case #%lld: ",t);
solve();
}
return 0;
}
负相关
hdu 4721 Food and Productivity
代码
#include<bits/stdc++.h>
#define f(i,j) for(int i=1;i<=j;i++)
using namespace std;
const int maxn = 510;
typedef pair<int,int> pii;
int N,M,R,Q,A,B;
int f[maxn][maxn];
int p[maxn][maxn];
int sf[maxn][maxn];
int sp[maxn][maxn];
int af[maxn][maxn];
int ap[maxn][maxn];
pii sb[maxn];
int SB[maxn];
int l;
set<pii>s;
inline int askf(int i,int j)
{
return sf[min(N,i+R)][min(M,j+R)]-sf[max(0,i-R-1)][min(M,j+R)]-sf[min(N,i+R)][max(0,j-R-1)]+sf[max(0,i-R-1)][max(0,j-R-1)];
}
inline int askp(int i,int j)
{
return sp[min(N,i+R)][min(M,j+R)]-sp[max(0,i-R-1)][min(M,j+R)]-sp[min(N,i+R)][max(0,j-R-1)]+sp[max(0,i-R-1)][max(0,j-R-1)];
}
void insert(pii x)
{
if(s.empty())
{
s.insert(x);
return;
}
else
{
set<pii>::iterator it=s.upper_bound(x);
if(it!=s.end()&&it->second>=x.second) return;
if(it==s.begin())
{
s.insert(x);
return;
}
--it;
while(1)
{
bool f=(it==s.begin());
if(it->second<=x.second)
{
if(f)
{
s.erase(it);
break;
}
else s.erase(it--);
}
else break;
}
s.insert(x);
}
}
void solve()
{
s.clear();
scanf("%d %d %d %d",&N,&M,&R,&Q);
f(i,N) f(j,M) scanf("%d",&f[i][j]);
f(i,N) f(j,M) scanf("%d",&p[i][j]);
f(i,N) f(j,M) sf[i][j]=sf[i-1][j]+sf[i][j-1]+f[i][j]-sf[i-1][j-1];
f(i,N) f(j,M) sp[i][j]=sp[i-1][j]+sp[i][j-1]+p[i][j]-sp[i-1][j-1];
f(i,N) f(j,M) af[i][j]=askf(i,j);
f(i,N) f(j,M) ap[i][j]=askp(i,j);
f(i,N) f(j,M) insert(make_pair(af[i][j],ap[i][j]));
l=0;
for(set<pii>::iterator it=s.begin();it!=s.end();++it)
{
sb[l]=*it;
SB[l]=sb[l].first-sb[l].second;
l++;
}
while(Q--)
{
scanf("%d %d",&A,&B);
int k=lower_bound(SB,SB+l,B-A)-SB;
int ans=0;
if(k<l) ans=max(ans,min(sb[k].first+A,sb[k].second+B));
if(k) ans=max(ans,min(sb[k-1].first+A,sb[k-1].second+B));
printf("%d\n",ans);
}
}
int main()
{
int T;
scanf("%d",&T);
f(t,T)
{
printf("Case #%d:\n",t);
solve();
if(t<T) puts("");
}
return 0;
}