B:普通前缀和即可
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10,M=2*N,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
using node=tuple<int,int,int>;
const long long inf=1e18;
int n,m,k;
int a[N];
int pre[N],suf[N];
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=n-1;i>=1;i--){
pre[i]=pre[i+1];
if(a[i]>=a[i+1])
pre[i]+=a[i]-a[i+1];
}
for(int i=2;i<=n;i++){
suf[i]=suf[i-1];
if(a[i]>=a[i-1])
suf[i]+=a[i]-a[i-1];
}
while(m--){
int l,r;cin>>l>>r;
if(l<r){
cout<<pre[l]-pre[r]<<"\n";
}else{
cout<<suf[l]-suf[r]<<"\n";
}
}
}
//1 2 3 4
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
//cin>>t;
while(t--) solve();
}
C:直接贪心,众所周知合法序列保证过程的权值要大于>=0即可,
特判如果过程中 cnt+now=1,now是负数,说明前面的cnt-1都要是(,当前问号只能做为(
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10,M=2*N,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
using node=tuple<int,int,int>;
const long long inf=1e18;
int n,m,k;
int a[N];
void solve()
{
string s;cin>>s;
int now=0,cnt=0;
for(auto x:s){
if(x=='(')
{
now++;
}
else if(x==')') now--;
else if(x=='?'){
cnt++;
}
if(cnt+now==1){
now=1;
cnt=0;
}
}
if(abs(now)!=cnt) cout<<"NO\n";
else
cout<<"YES\n";
}
//1 2 3 4
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
D:首先如果坐标差不是k的倍数就不行,然后直接贪心,让我起始点往下走往右再往上就行,
如果中间段最大值卡住就不行
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10,M=2*N,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
using node=tuple<int,int,int>;
const long long inf=1e18;
int n,m,k;
int a[N];
int f[N][35];
void init(){
for(int i=0;i<=30;i++){
for(int j=1;j+(1<<i)-1<=m;j++){
if(!i) f[j][i]=a[j];
else f[j][i]=max(f[j][i-1],f[j+(1<<i-1)][i-1]);
}
}
}
int query(int l,int r){
int len=r-l+1;
int k=log(len)/log(2);
//x+(1<<k)-1=r
return max(f[l][k],f[r-(1<<k)+1][k]);
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>a[i];
}
init();
int q;cin>>q;
while(q--)
{
int xs,ys,xf,yf,k;
cin>>xs>>ys>>xf>>yf>>k;
if(abs(xs-xf)%k || abs(ys-yf)%k){
cout<<"NO\n";
continue;
}
if(ys>yf){
swap(ys,yf);
swap(xs,xf);
}
int cnt=(n-xs)/k;
xs+=cnt*k;
if(query(ys,yf)<xs){
cout<<"YES\n";
}else cout<<"NO\n";
}
}
//1 2 3 4
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
//cin>>t;
while(t--) solve();
}
E:
因为让每个路径异或和都不为0,就是让每个子树的异或和不为0,
x到y的路径异或和= d[x]^d[y]^a[lca(x,y)]
启发式合并的时候判断是不是有重复的即可,如果重复直接改变根的权值,因为大小不变
所以可以直接在 2>>100次方放个1就行,
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10,M=2*N,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
using node=tuple<int,int,int>;
const long long inf=1e18;
int n,m,k;
int a[N];
vector<int> g[N];
int d[N];
set<int> st[N];
int res;
void dfs(int u,int fa)
{
for(auto v:g[u]){
if(v==fa) continue;
d[v]=(a[v]^d[u]);
dfs(v,u);
}
}
void dfs1(int u,int fa){
st[u].insert(d[u]);
bool f=false;
for(auto v:g[u])
{
if(v==fa) continue;
dfs1(v,u);
if(st[u].size()<st[v].size())
{
swap(st[u],st[v]);
}
for(auto k:st[v])
{
if(st[u].count(k^a[u]))
{
f=true;
}
//根:d[u]^d[v]^a[u]=0
//路径=d[x]^d[y]^a[u]==0
}
for(auto k:st[v])
st[u].insert((k));
}
if(f){
res++;
st[u].clear();
}
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<n;i++){
int x,y;cin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
res=0;
d[1]=a[1];
dfs(1,0);
dfs1(1,0);
cout<<res<<"\n";
}
//1 2 3 4
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
//cin>>t;
while(t--) solve();
}