T1
不难发现,如果说只删第一个,那就是留后缀,只删第二个,那就是第一个加上后缀。
而先做第二个,再做第一个是没有意义的,我可以做总个数加一次的第一个来达成目标。
所以相当于是说,我只会先做第一个,再做第二个。
所以就相当于是选出来其中一个位置,然后它的后缀里面所有的情况。
枚举后缀即可。
点击查看代码#include
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=1e6+5;
int n,cnt[26];
string s;
void solve()
{cin>>n>>s;s=' '+s;int ans=0;memset(cnt,0,sizeof(cnt));for(int i=1;i<=n;i++) cnt[s[i]-'a']++;for(int i=n;i>=1;i--){int tmp=0;for(int j=0;j<26;j++) tmp+=(cnt[j]>0);ans+=tmp;cnt[s[i]-'a']--;}cout<>t;while(t--) solve();return 0;
}
T2
由于遇到重复的情况,需要算。
所以就要预处理出来所有被多少个区间覆盖。
而对于重复计算的问题,会发现,只有其长度小于等于 \(d\) 的时候。才会发生重复
所以考虑用数上数组维护特殊的情况。至于普通情况直接加就行。
点击查看代码#include
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=3e5+5;
vector v[300005];
int bit[300005],ans[300005],n,l[600005],r[600005];
int lb(int x)
{return x&-x;
}
void update(int x,int y)
{while(x<=n) bit[x]+=y,x+=lb(x);
}
int query(int x,int ans=0)
{while(x) ans+=bit[x],x-=lb(x);return ans;
}
signed main()
{freopen("jump.in","r",stdin);freopen("jump.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int m,q;cin>>n>>m>>q;for(int i=1;i<=m;i++) cin>>l[i]>>r[i],v[r[i]-l[i]+1].push_back(i);int cnt=m;for(int i=1;i<=n;i++){for(int j:v[i]) cnt--,update(l[j],1),update(r[j]+1,-1);ans[i]=cnt;for(int j=i;j<=n;j+=i) ans[i]+=query(j);}while(q--){int x;cin>>x;cout<
T3
显然,需要树形dp。
设 \(f_i\) 表示,在以i为根的指数下,能够找到的期望步数是多少
显然还是算不了答案
那么我们可以先假定他的儿子的访问顺序
这样子就可以计算了
而方式,这就是典型的“国王游戏”
排完序后计算即可
点击查看代码#include
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5,mod=1e9+7;
vector g[maxn];
int dp[maxn],f[maxn],siz[maxn],inv[maxn];
char c[maxn];
int kasumi(int a,int b=mod-2,int ans=1)
{while(b){if(b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;}return ans;
}
bool cmp(int x,int y)
{return siz[y]*(f[x]+2)>n;inv[1]=1;for(int i=2;i<=n;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;for(int i=2;i<=n;i++){int x;cin>>x>>c[i];g[x].push_back(i);}dfs(1),cout<