FGHJK
I不会斯坦纳树,E看情况补
ABCD大概率是不会补了
注意到互不相同的环长最多为根号个
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int p[13][N];
int ret[300][N],id[N];
int main()
{
int n,m,q;
while(scanf("%d%d%d",&n,&m,&q)!=EOF)
{
for(int i=1;i<=n;++i)p[0][i]=i;
for(int i=1,a,b;i<=m;++i)
{
for(int j=1;j<=n;++j)p[i][j]=p[i-1][j];
scanf("%d%d",&a,&b);
reverse(p[i]+a,p[i]+b+1);
}
//for(int i=1;i<=n;++i)printf("%d%c",p[m][i]," \n"[i==n]);
vector<int>vis(n+1),rs(q),ques(q);
for(auto &v:ques)scanf("%d",&v);
vector<vector<int>> Q(m);
for(int i=0;i<q;++i)Q[ques[i]%m].push_back(i);
//circ
vector<int> circ,from(n+1),dis(n+1);
map<int,int> hv;
unordered_map<int,int> mp;
int cnt=0;
for(int i=1;i<=n;++i)
if(!vis[i])
{
int L=0;
++cnt;
for(int pos=i;!vis[pos];pos=p[m][pos])
++vis[pos],from[pos]=cnt,dis[pos]=++L;
mp[cnt]=L;
hv[L]=1;
//cout<<"L"<<L<<endl;
}
for(auto [L,v]:hv)circ.push_back(L);
// cout<<
// for(auto L:circ)cout<<L<<" ";cout<<endl;
//cout<<circ.size()<<endl;
for(int i=0;i<circ.size();++i)id[circ[i]]=i;
for(int i=0;i<m;++i)
if(Q[i].size())
{
// cout<<"i== "<<i<<endl;
// map<pair<int,int>,int> res;
for(int j=1;j<=n;++j)
{
int u=j,v=p[i][j];
if(from[u]!=from[v])continue;
int L=mp[from[u]];
int d=(dis[u]-dis[v]+L)%L;
ret[id[L]][d]++;
//cout<<"L=="<<L<<endl;
//cout<<"now "<<endl;
}
for(auto v:Q[i])
{
for(auto L:circ)
{
rs[v]+=ret[id[L]][(ques[v]/m)%L];
//cout<<v<<" "<<rs<<endl;
}
}
for(int j=0;j<circ.size();++j)
for(int k=0;k<=circ[j];++k)
ret[j][k]=0;
}
for(auto v:rs)printf("%d\n",v);
}
}
G
排列 |
注意到数据范围,考虑状压
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
ll cal(int state)
{
return __builtin_popcount(state);
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
vector<int> p(n);
for(auto &v:p)scanf("%d",&v);
sort(p.begin(),p.end());
map<int,int> mp;
for(int i=1,x,y;i<=m;++i)
{scanf("%d%d",&x,&y);--x,--y;mp[x]|=1<<y;mp[y]|=1<<x;}
vector<ll> dp(1<<n,1e18);
dp[0]=0;
for(int i=1;i<1<<n;++i)
{
int t=__builtin_popcount(i)-1;
for(int j=0;j<n;++j)
if(i&1<<j)
{
dp[i]=min(dp[i],dp[i^(1<<j)]+1ll*(cal(mp[j]&i)*2-cal(mp[j]))*p[t]);
}
}
printf("%lld\n",dp[(1<<n)-1]);
}
}
注意到操作2范围很小,可以考虑暴力拆成3各部分
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct segment
{
struct Node
{
int l,r,val,lz;
int mid(){return l+r>>1;}
bool in(int L,int R){return l>=L&&r<=R;}
bool is_dot(){return l==r;}
}tr[N<<2];
void build(int u,int l,int r)
{
tr[u]={l,r,0,0};
if(l==r)return;
int mid=tr[u].mid();
build(u<<1,l,mid);build(u<<1|1,mid+1,r);
}
void pushdown(int u)
{
if(tr[u].is_dot())return ;
if(!tr[u].lz)return ;
// Node &ls=tr[u<<1],&rs=tr[u<<1|1];
tr[u<<1].val+=tr[u].lz;tr[u<<1|1].val+=tr[u].lz;
tr[u<<1].lz+=tr[u].lz;tr[u<<1|1].lz+=tr[u].lz;
tr[u].lz=0;
}
void pushup(int u)
{
return ;
}
void modify(int u,int l,int r,int x)
{
if(tr[u].in(l,r))
{
tr[u].val+=x;tr[u].lz+=x;return ;
}
pushdown(u);
int mid=tr[u].mid();
if(l<=mid)modify(u<<1,l,r,x);
if(r>mid)modify(u<<1|1,l,r,x);
pushup(u);
}
int query_dot(int u,int pos)
{
if(tr[u].is_dot())return tr[u].val;
int mid=tr[u].mid();
pushdown(u);
if(pos<=mid)return query_dot(u<<1,pos);
return query_dot(u<<1|1,pos);
}
};
int main()
{
int n,q;
while(scanf("%d%d",&n,&q)!=EOF)
{
segment seg;
seg.build(1,1,n);
vector<int> d0(n+1),d1(n+1);
while(q--)
{
int t,l,r;scanf("%d%d%d",&t,&l,&r);
if(t==1)
{
seg.modify(1,l,r,1);
if(r-l>=0)++d0[r];
if(r-l>=1)++d1[r];
}
else
{
int rs=seg.query_dot(1,l);
if(r-l>0)rs-=d0[l];
if(r-l>1)rs-=d1[l+1];
printf("%d\n",rs);
}
}
}
}
J买一送一
很一眼的傻逼题
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=5e5+10;
vector<int> e[N];
ll sm=0;
int a[N];
map<int,int>lst,mp;
vector<int>stk;
ll f[N];
void dfs(int u)
{
mp[a[u]]++;
ll back=sm;
sm=sm-lst[a[u]]+(int)stk.size();
f[u]=sm;
ll t=lst[a[u]];
lst[a[u]]=stk.size();
if(mp[a[u]]==1)stk.push_back(a[u]);
for(auto v:e[u])
{
dfs(v);
}
lst[a[u]]=t;
if(mp[a[u]]==1)stk.pop_back();
--mp[a[u]];
sm=back;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
sm=0;mp.clear();lst.clear();stk.clear();
for(int i=1;i<=n;++i)e[i].clear();
for(int i=2,x;i<=n;++i)
{
scanf("%d",&x);
e[x].push_back({i});
}
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
dfs(1);
for(int i=2;i<=n;++i)printf("%lld\n",f[i]);}
}
K
Use FFT |
名字是FFT,一看是前缀和
#include <bits/stdc++.h>
using namespace std;
const int P=1e9+7;
using ll=long long;
void add(int &a,int b){a+=b;if(a>=P)a-=P;}
int main()
{
int n,m,L,R;
while(scanf("%d%d%d%d",&n,&m,&L,&R)!=EOF)
{
vector<int> a(n+1),b(m+1);
for(auto &v:a)scanf("%d",&v);
for(auto &v:b)scanf("%d",&v);
for(int i=1;i<=m;++i)add(b[i],b[i-1]);
int rs=0;
for(int i=0;i<=n;++i)
if(R-i>=0)
add(rs,1ll*(b[min(m,R-i)]+P-((L-i-1>=0)?b[min(L-i-1,m)]:0))*a[i]%P);
printf("%d\n",rs);
}
}