1.2017广西南宁icpc邀请赛(7/13)
http://acm.hdu.edu.cn/search.php?field=problem&key=2017ACM%2FICPC%B9%E3%CE%F7%D1%FB%C7%EB%C8%FC-%D6%D8%CF%D6%C8%FC%A3%A8%B8%D0%D0%BB%B9%E3%CE%F7%B4%F3%D1%A7%A3%A9&source=1&searchmode=source
A 暴力即可,注意爆ll
B 一共有时间,x,y,颜色四个维度,先开50棵动态开点线段树,维护颜色维度,然后线段树上按照y轴维护每个y坐标上最小的x值,最后按照时间在线回答即可
#include <bits/stdc++.h>
#define endl '\n'
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e6+10,maxm=2e7+10;
int casn,n,m,k;
int root[60];
class dsegtree{public:
#define nd node[now]
#define ndl node[node[now].son[0]]
#define ndr node[node[now].son[1]]
struct dsegnode{
int son[2],mn;
void update(int x){mn=min(mn,x);}
}node[maxm];
int cnt;
void init(){
memset(root,0,sizeof root);
node[0]={0,0,(int)1e9};
cnt=0;
}
void pushup(int now){nd.mn=min(ndl.mn,ndr.mn);}
void update(int pos,int x,int l,int r,int &now){
if(!now) now=++cnt,nd={0,0,x};
if(l==r) {nd.update(x);return ;}
if(pos<=(l+r)>>1) update(pos,x,l,(l+r)>>1,nd.son[0]);
else update(pos,x,1+((l+r)>>1),r,nd.son[1]);
pushup(now);
}
int query(int s,int t,int l,int r,int now){
if(!now) return 1e9;
if(s<=l&&t>=r) return nd.mn;
if(t<=(l+r)>>1) return query(s,t,l,(l+r)>>1,nd.son[0]);
if(s>(l+r)>>1) return query(s,t,1+((l+r)>>1),r,nd.son[1]);
return min(query(s,t,l,(l+r)>>1,nd.son[0]),query(s,t,1+((l+r)>>1),r,nd.son[1]));
}
}tree;
int main() {
IO;
int a,b,c,d;
while(cin>>a){
if(a==3) break;
if(a==0) tree.init();
if(a==1||a==2){
cin>>b>>c>>d;
if(a==1) tree.update(c,b,1,maxn,root[d]);
else {
int ans=0;
rep(i,0,50)ans+=(tree.query(c,d,1,maxn,root[i])<=b);
cout<<ans<<endl;
}
}
}
return 0;
}
C 三元环计数,答案就是Σ(每个边被三元环包含的次数^2-每个边被三元环包含的次数)/2
#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define fi first
#define se second
#define pii pair<int,int>
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=2e5+10,maxm=2e6+10;
//head
int casn,n,m,k;
vector<pii>g[maxn];
int deg[maxn],a[maxn],b[maxn],cnt[maxn],pos[maxn],v[maxn];
int main() {
IO;
while(cin>>n>>m){
rep(i,1,n){
g[i].clear();
v[i]=deg[i]=pos[i]=0;
}
rep(i,1,m){
cin>>a[i]>>b[i];
deg[a[i]]++,deg[b[i]]++;
}
rep(i,1,m){
cnt[i]=0;
if(deg[a[i]]<deg[b[i]])g[a[i]].emplace_back(b[i],i);
else if(deg[a[i]]>deg[b[i]])g[b[i]].emplace_back(a[i],i);
else {
if(a[i]<b[i]) g[a[i]].emplace_back(b[i],i);
else g[b[i]].emplace_back(a[i],i);
}
}
rep(i,1,m){
int u=a[i],to=b[i];
for(auto j:g[u]) pos[j.fi]=j.se,v[j.fi]=i+1;
for(auto j:g[to]){
int t=j.fi;
if(v[t]==i+1){
cnt[i]++;
cnt[pos[t]]++;
cnt[j.se]++;
}
}
}
ll ans=0;
rep(i,1,m) ans+=1ll*cnt[i]*(cnt[i]-1)/2;
cout<<ans<<endl;
}
return 0;
}
D 递推+矩阵快速幂,记录一下完全体的矩阵板子
#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e6+10,maxm=2e6+10;
const ll mod=1e9+7;
ll n,m,casn,q,k;
class matrix{public://带取模
int a,b;
vector<vector<ll> > x;
matrix(int a=1,int b=1){//行数,列数,初始均为0
this->a=a,this->b=b;
x.resize(a);
for(auto &i:x){i.resize(b);std::fill(all(i),0);}
}
void e(int n){a=b=n;x=matrix(n,n).x;for(int i=0;i<n;i++)x[i][i]=1;}//n*n的单位矩阵
void fill(ll xx=0){for(int i=0;i<a;i++)for(int j=0;j<b;j++)x[i][j]=xx;} //全部填为xx
void fill(vector<vector<ll>> &y){x=y;a=y.size();b=y[0].size();}//用二维数组填充
matrix operator *(matrix &m){
matrix ans(a,m.b);
for(int i=0;i<a;i++)for(int j=0;j<m.b;j++)for(int k=0;k<b;k++)if(x[i][k]&&m.x[k][j])
ans.x[i][j]=(mod+ans.x[i][j]+(x[i][k]*m.x[k][j]+mod)%mod)%mod;
return ans;
}
matrix operator +(matrix &m){
matrix ans(a,m.b);
for(int i=0;i<a;i++)for(int j=0;j<b;j++)ans.x[i][j]=(x[i][j]+m.x[i][j]+mod)%mod;
return ans;
}
matrix operator -(matrix &m){
matrix ans(a,m.b);
for(int i=0;i<a;i++)for(int j=0;j<b;j++)ans.x[i][j]=(x[i][j]-m.x[i][j]+mod)%mod;
return ans;
}
matrix pow(ll p){//快速幂
matrix ans;ans.e(a);matrix t;t.fill(x);
while(p){if(p&1) ans=t*ans;t=t*t;p>>=1;}return ans;
}
};
const ll ff[4][4]={1,1,0,0,5,0,1,0,1,0,0,1,-1,0,0,0};
const ll fc[4]={1,5,11,36};
int main() {
IO;
vector<vector<ll> > f0(4,vector<ll>(4,0)),f1(1,vector<ll>(4,0));
rep(i,0,3){
rep(j,0,3) f0[i][j]=ff[i][j];
f1[0][i]=fc[3-i];
}
while(cin>>n){
if(n<=4) {
cout<<fc[n-1]<<endl;
continue;
}
matrix ans; ans.fill(f1);
matrix c; c.fill(f0);
c=c.pow(n-4);
ans=ans*c;
cout<<ans.x[0][0]<<endl;
}
}
E 前缀+后缀即可,注意边界
G 贪心,先拿走所有2个以上的部分,然后连续三个的优先级为:112 > 2XX > 111
J dfs序+01字典树,可以离线也可以持久化
离线:
#include <bits/stdc++.h>
#define endl '\n'
#define all(x) x.begin(),x.end()
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e5+10,maxm=2e6+10;
//head
int casn,n,m,k;
vector<int> g[maxn];
class trie{public:
int node[maxn*40][3],top;
void init(){memset(node[0],0,sizeof (node[0]));top=1;}
void add(int x,int id){
int now,nx,rt,t;
for(rt=0,t=31;~t;rt=nx,--t){
nx=node[rt][now=x>>t&1];
if(!nx) memset(node[top],0,sizeof (node[top])),node[rt][now]=nx=top++;
node[nx][2]=id;
}
}
int query(int x,int l){
int rt,nx,now,t,ans=0;
for(rt=0,t=31;~t;rt=nx,--t){
now=x>>t&1,ans<<=1;
if((nx=node[rt][!now])&&node[nx][2]<=l)ans+=1;
else nx=node[rt][now];
}
return ans;
}
}tree;
struct node{
int id,x,l,r;
bool operator<(node &n)const {return l>n.l;}
}ask[maxn];
int in[maxn],out[maxn],id[maxn];
int cnt,val[maxn],ans[maxn];
void dfs(int now){
in[now]=++cnt;id[cnt]=now;
for(auto i:g[now]) dfs(i);
out[now]=cnt;
}
int main() {
IO;
while(cin>>n>>k){
cnt=0;
tree.init();
rep(i,1,n) g[i].clear();
rep(i,1,n) cin>>val[i];
rep(i,2,n){
int x;cin>>x;
g[x].push_back(i);
}
dfs(1);
rep(i,1,k){
int a,b;cin>>a>>b;
ask[i]={i,b,in[a],out[a]};
}
sort(ask+1,ask+1+k);
int pos=n;
rep(i,1,k){
while(pos>=ask[i].l) tree.add(val[id[pos]],pos),--pos;
ans[ask[i].id]=tree.query(ask[i].x,ask[i].r);
}
rep(i,1,k) cout<<ans[i]<<endl;
}
return 0;
}
持久化字典树
#include <bits/stdc++.h>
#define endl '\n'
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e5+10,maxm=2e6+10;
//head
int casn,n,m,k;
int rt[maxn];
vector<int> g[maxn];
class ptrie{public:
int node[maxn*40][2],top;
void init(){rt[0]=node[0][1]=node[0][0]=top=0;}
int add(int pre,int val,int bit=31){
int now=++top;
if(bit<0) return now;
int t=val>>bit&1;
node[now][t]=add(node[pre][t],val,bit-1);
node[now][t^1]=node[pre][t^1];
return now;
}
int query(int now,int pre,int val,int bit=31,int ans=0){
if(bit<0) return ans;
int t=val>>bit&1;
if(node[now][t^1]-node[pre][t^1]>0) return query(node[now][t^1],node[pre][t^1],val,bit-1,ans|(1<<bit));
return query(node[now][t],node[pre][t],val,bit-1,ans);
}
}tree;
int in[maxn],out[maxn];
int cnt,val[maxn];
void dfs(int now){
in[now]=++cnt;
rt[cnt]=tree.add(rt[cnt-1],val[now]);
for(auto i:g[now]) dfs(i);
out[now]=cnt;
}
int main() {
IO;
while(cin>>n>>k){
cnt=0;
tree.init();
rep(i,1,n) g[i].clear();
rep(i,1,n) cin>>val[i];
rep(i,2,n){
int x;cin>>x;
g[x].push_back(i);
}
dfs(1);
rep(i,1,k){
int a,b;cin>>a>>b;
cout<<tree.query(rt[out[a]],rt[in[a]-1],b)<<endl;
}
}
return 0;
}
2