sb题,我们前缀后缀和一下直接O(N)算贡献就可以了
#include
#include
#include
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int INF=0x3f3f3f3f;
const int N=500005;
char s[N];
int main(void) {
int n; scanf("%d%s",&n,s+1);
int L=0,R=0,ans=INF;
rep(i,1,n) R+=(s[i]=='E');
rep(i,1,n) {
R-=(s[i]=='E');
ans=std:: min(ans,L+R);
R+=(s[i]=='W');
}
printf("%d\n", ans);
return 0;
}
有一个小结论就是a^b<=a+b恒成立。证明的话,可以发现异或运算被称为不进位加法?
因此做法就十分显然了。我们枚举右端点,那么合法的左端点一定是连续一段,这个可以用二分找出来。
预处理前缀和前缀异或和就是O(NlogN)了
#include
#include
#include
#include
#include
#include
#include
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
#define fill(x,t) memset(x,t,sizeof(x))
#define copy(x,t) memcpy(x,t,sizeof(x))
#define fi first
#define se second
typedef std:: pair <int,int> pair;
typedef long double ld;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
const int ny2=(MOD+1)/2;
const int N=2000005;
const ld pi=acos(-1);
const ld e=exp(1);
const ld eps=1e-8;
LL a[N],s[N],t[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
int main(void) {
int n=read();
rep(i,1,n) {
a[i]=read();
s[i]=s[i-1]+a[i];
t[i]=t[i-1]^a[i];
}
LL ans=0;
rep(i,1,n) {
int l=1,r=i,pos=1;
while (l<=r) {
int mid=(l+r)>>1;
if ((s[i]-s[mid-1])==(t[i]^t[mid-1])) {
r=mid-1,pos=mid;
} else l=mid+1;
}
ans+=(i-pos+1);
}
printf("%lld\n", ans);
return 0;
}
考虑枚举最小值mn。我们钦定比mn小的数都不能取
为了使答案最小,我们需要选取能选的数中第k小的,记为mx,然后用mx-mn更新答案就可以了
找哪些数字可选就直接用vector抠出来,然后std排序就完了。这样做是O(N2logN) 的
#include
#include
#include
#include
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int INF=0x3f3f3f3f;
const int N=20005;
int a[N],b[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
int main(void) {
freopen("data.in","r",stdin);
int n=read(),k=read(),q=read();
rep(i,1,n) b[i]=a[i]=read();
std:: sort(b+1,b+n+1);
int ans=INF;
rep(ti,1,n) {
int mn=b[ti];
std:: vector <int> v,r;
v.push_back(0);
rep(i,1,n) if (a[i]<mn) v.push_back(i);
v.push_back(n+1);
int pre=v[0];
for (int i=1;i<v.size();++i) {
int now=v[i];
int len=now-pre-1;
if (len<k) {pre=now; continue;}
std::vector <int> s;
rep(j,pre+1,now-1) s.push_back(a[j]);
std:: sort(s.begin(),s.end());
rep(j,0,len-k) r.push_back(s[j]);
pre=now;
}
std:: sort(r.begin(),r.end());
if (q<=r.size()) ans=std:: min(ans,r[q-1]-mn);
}
printf("%d\n", ans);
return 0;
}
连续两次都读错题意了。。语死早吃枣药丸
感觉这题都讲得好感性啊。。要不意识流一波混过去吧。。
记C[i]=max(A[i]-B[i],0),那么A的限制就变成了,除了要捐的B元,我们还需要多带上C这么多钱
很容易发现我们肯定优先捐C较小的,也就是意味着我们可以多次经过某个位置但是只有最后一次捐钱
并且可以知道,我们一定是选择一个C最大的位置x作为起点,出发捐完若干连通块->回到x并捐x->捐剩下的一个连通块(当然也可能没有剩下)
为啥呢?首先我们发现随着访问节点变多,答案是不降的。那么就可能存在某个位置,使得它在x前捐不会让答案变小,在x后捐不会让答案变大。因此是可能存在连通块剩余的。
其次可以知道捐完x之后若有连通块剩余,那么一定只会剩下一个连通块。因为我们不会再回到x
观察到每个连通块与原图的做法是一模一样的,于是我们按照C排序,枚举每一个连通块的根然后建出树,在树上dp就可以了
#include
#include
#include
#include
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
typedef long long LL;
const LL INF=1e18;
const int N=200005;
std:: vector <int> E[N],G[N];
LL a[N],b[N],f[N],g[N];
int fa[N],rk[N];
bool vis[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void dfs(int x) {
if (G[x].empty()) {
f[x]=a[x]+b[x],g[x]=b[x];
return ;
}
g[x]=b[x],f[x]=INF;
for (int y:G[x]) dfs(y),g[x]+=g[y];
for (int y:G[x]) {
f[x]=std:: min(f[x],std:: max(f[y],a[x])+g[x]-g[y]);
}
}
int find(int x) {
return !fa[x]?x:(fa[x]=find(fa[x]));
}
bool cmp(int x,int y) {
return a[x]<a[y];
}
int main(void) {
freopen("data.in","r",stdin);
int n=read(),m=read();
rep(i,1,n) {
a[i]=read(),b[i]=read();
a[i]=std:: max(a[i]-b[i],0LL);
rk[i]=i;
}
rep(i,1,m) {
int x=read(),y=read();
E[x].push_back(y);
E[y].push_back(x);
}
std:: sort(rk+1,rk+n+1,cmp);
rep(ti,1,n) {
int x=rk[ti]; vis[x]=1;
for (int y:E[x]) {
if (!vis[y]) continue;
if (find(y)==find(x)) continue;
G[x].push_back(find(y));
fa[find(y)]=find(x);
}
}
rep(i,1,n) if (find(i)==i) {
dfs(i),printf("%lld\n", f[i]);
}
return 0;
}